[vlc-devel] [PATCH] win32: in debug builds make sure the non-recursive locks are not reentrant

Steve Lhomme robux4 at videolabs.io
Sun Jun 5 14:15:52 CEST 2016


Use a semaphore with a single token for non recursive locks
Use the same code as non-debug builds with recursive locks
---
 include/vlc_threads.h | 10 ++++++++++
 src/win32/thread.c    | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git a/include/vlc_threads.h b/include/vlc_threads.h
index 33b9b53..b0f2259 100644
--- a/include/vlc_threads.h
+++ b/include/vlc_threads.h
@@ -52,6 +52,12 @@ VLC_API void vlc_testcancel(void);
 #  define ETIMEDOUT 10060 /* This is the value in winsock.h. */
 # endif
 
+#ifndef NDEBUG
+#define MUTEX_ALWAYS_RECURSIVE 0
+#else
+#define MUTEX_ALWAYS_RECURSIVE 1
+#endif
+
 typedef struct vlc_thread *vlc_thread_t;
 # define VLC_THREAD_CANCELED NULL
 # define LIBVLC_NEED_SLEEP
@@ -66,6 +72,10 @@ typedef struct
             unsigned long contention;
         };
         CRITICAL_SECTION mutex;
+#if !MUTEX_ALWAYS_RECURSIVE
+        HANDLE hMutex; /* non-recursive semaphore */
+        unsigned long lock_thread_id;
+#endif
     };
 } vlc_mutex_t;
 #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 963a8d7..c8b1a09 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -71,13 +71,20 @@ void vlc_mutex_init( vlc_mutex_t *p_mutex )
 {
     /* This creates a recursive mutex. This is OK as fast mutexes have
      * no defined behavior in case of recursive locking. */
+#if MUTEX_ALWAYS_RECURSIVE
     InitializeCriticalSection (&p_mutex->mutex);
+#else
+    p_mutex->hMutex = CreateSemaphore( NULL, 1, 1, NULL );
+#endif
     p_mutex->dynamic = true;
 }
 
 void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
 {
     InitializeCriticalSection( &p_mutex->mutex );
+#if !MUTEX_ALWAYS_RECURSIVE
+    p_mutex->hMutex = INVALID_HANDLE_VALUE;
+#endif
     p_mutex->dynamic = true;
 }
 
@@ -85,6 +92,11 @@ void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
 void vlc_mutex_destroy (vlc_mutex_t *p_mutex)
 {
     assert (p_mutex->dynamic);
+#if !MUTEX_ALWAYS_RECURSIVE
+    if ( p_mutex->hMutex != INVALID_HANDLE_VALUE )
+        CloseHandle( p_mutex->hMutex );
+    else
+#endif
     DeleteCriticalSection (&p_mutex->mutex);
 }
 
@@ -108,6 +120,15 @@ void vlc_mutex_lock (vlc_mutex_t *p_mutex)
         return;
     }
 
+#if !MUTEX_ALWAYS_RECURSIVE
+    if ( p_mutex->hMutex != INVALID_HANDLE_VALUE )
+    {
+        assert(p_mutex->lock_thread_id != vlc_thread_id());
+        WaitForSingleObject( p_mutex->hMutex, INFINITE );
+        p_mutex->lock_thread_id = vlc_thread_id();
+    }
+    else
+#endif
     EnterCriticalSection (&p_mutex->mutex);
 }
 
@@ -128,6 +149,20 @@ int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
         return ret;
     }
 
+#if !MUTEX_ALWAYS_RECURSIVE
+    if ( p_mutex->hMutex != INVALID_HANDLE_VALUE )
+    {
+        assert(p_mutex->lock_thread_id != vlc_thread_id());
+        if ( WaitForSingleObject( p_mutex->hMutex, 0 ) == WAIT_OBJECT_0 )
+        {
+            p_mutex->lock_thread_id = vlc_thread_id();
+            return 0;
+        }
+        else
+            return EBUSY;
+    }
+    else
+#endif
     return TryEnterCriticalSection (&p_mutex->mutex) ? 0 : EBUSY;
 }
 
@@ -146,6 +181,14 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
         return;
     }
 
+#if !MUTEX_ALWAYS_RECURSIVE
+    if ( p_mutex->hMutex != INVALID_HANDLE_VALUE )
+    {
+        p_mutex->lock_thread_id = 0;
+        ReleaseSemaphore( p_mutex->hMutex, 1, NULL );
+    }
+    else
+#endif
     LeaveCriticalSection (&p_mutex->mutex);
 }
 
-- 
2.7.0



More information about the vlc-devel mailing list