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

Steve Lhomme robux4 at videolabs.io
Thu Jun 2 11:23:24 CEST 2016


Use a semaphore with a single token for non recursive locks
Use a mutex for 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 33f2a8a..e2602fc 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
 typedef struct
@@ -65,6 +71,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 88aaa5b..27dd175 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -137,13 +137,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;
 }
 
@@ -151,6 +158,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);
 }
 
@@ -174,6 +186,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);
 }
 
@@ -194,6 +215,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;
 }
 
@@ -212,6 +247,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.8.1



More information about the vlc-devel mailing list