[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