[vlc-devel] [PATCH] win32: in debug builds make sure the non-recursive locks are not reentrant
Rémi Denis-Courmont
remi at remlab.net
Sun Jun 5 14:41:09 CEST 2016
Le 2016-06-05 14:35, Steve Lhomme a écrit :
> Use a semaphore with a single token for non recursive locks
> Use the same code as non-debug builds with recursive locks
>
> --
> hopefully fixes the make check header issue in
> https://patches.videolan.org/patch/13618/
> ---
> include/vlc_threads.h | 4 ++++
> src/win32/thread.c | 49
> +++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 53 insertions(+)
>
> diff --git a/include/vlc_threads.h b/include/vlc_threads.h
> index 33b9b53..08b10f2 100644
> --- a/include/vlc_threads.h
> +++ b/include/vlc_threads.h
> @@ -66,6 +66,10 @@ typedef struct
> unsigned long contention;
> };
> CRITICAL_SECTION mutex;
> +
> + /* non-recursive semaphore */
> + HANDLE hMutex;
> + unsigned long lock_thread_id;
> };
> } vlc_mutex_t;
> #define VLC_STATIC_MUTEX { false, { { false, 0 } } }
> diff --git a/src/win32/thread.c b/src/win32/thread.c
> index 963a8d7..0fab5ad 100644
> --- a/src/win32/thread.c
> +++ b/src/win32/thread.c
> @@ -43,6 +43,12 @@
> static vlc_mutex_t super_mutex;
> static vlc_cond_t super_variable;
>
> +#ifndef NDEBUG
> +#define MUTEX_ALWAYS_RECURSIVE 0
> +#else
> +#define MUTEX_ALWAYS_RECURSIVE 1
> +#endif
> +
> #define IS_INTERRUPTIBLE (!VLC_WINSTORE_APP || _WIN32_WINNT >=
> 0x0A00)
>
> /*** Threads ***/
> @@ -71,13 +77,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
Isn't a mutex a lot slower than a critical section, as it's a kernel
handle? If you want to rule out recursive locking, you just need a
boolean on top of the critical section, AFAICT.
> 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 +98,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 +126,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());
What prevents another thread from writing lock_thread_id concurrently?
> + WaitForSingleObject( p_mutex->hMutex, INFINITE );
> + p_mutex->lock_thread_id = vlc_thread_id();
> + }
> + else
> +#endif
> EnterCriticalSection (&p_mutex->mutex);
> }
>
> @@ -128,6 +155,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 +187,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);
> }
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list