[vlc-devel] [PATCH 1/2] win32: implement non-recursive locks

Steve Lhomme robux4 at gmail.com
Fri Jun 24 08:33:03 CEST 2016


On Fri, Jun 24, 2016 at 4:49 AM, Rémi Denis-Courmont <remi at remlab.net> wrote:
> Le 2016-06-21 12:56, Steve Lhomme a écrit :
>>
>> locked & b_recursive are always accessed in the CriticalSection
>
>
> It probably works, but I still don't see why you need a counter, insofar as
> you use a Win32 critical section. The recursion counter is already provided
> by Win32. AFAICT, a boolean is enough.

The counter allows this assert in vlc_mutex_unlock()
assert(p_mutex->locked >= 0);

So we can catch un-matched unlocks. Also if we don't we can end up in
harder to decypher blocking issues. Here's the doc of
LeaveCriticalSection()

"If a thread calls LeaveCriticalSection when it does not have
ownership of the specified critical section object, an error occurs
that may cause another thread using EnterCriticalSection to wait
indefinitely."

>>
>> --
>> simple rebase of https://patches.videolan.org/patch/13641/
>> ---
>>  include/vlc_threads.h | 12 +++++-------
>>  src/win32/thread.c    | 30 ++++++++++++++++++++++++------
>>  2 files changed, 29 insertions(+), 13 deletions(-)
>>
>> diff --git a/include/vlc_threads.h b/include/vlc_threads.h
>> index 33b9b53..1fe22bf 100644
>> --- a/include/vlc_threads.h
>> +++ b/include/vlc_threads.h
>> @@ -57,18 +57,16 @@ typedef struct vlc_thread *vlc_thread_t;
>>  # define LIBVLC_NEED_SLEEP
>>  typedef struct
>>  {
>> +    int locked;
>> +    bool b_recursive;
>>      bool dynamic;
>>      union
>>      {
>> -        struct
>> -        {
>> -            bool locked;
>> -            unsigned long contention;
>> -        };
>> -        CRITICAL_SECTION mutex;
>> +        unsigned long contention; /* static */
>> +        CRITICAL_SECTION mutex;   /* dynamic */
>>      };
>>  } vlc_mutex_t;
>> -#define VLC_STATIC_MUTEX { false, { { false, 0 } } }
>> +#define VLC_STATIC_MUTEX { 0, false, false, { 0 } }
>>  #define LIBVLC_NEED_CONDVAR
>>  #define LIBVLC_NEED_SEMAPHORE
>>  #define LIBVLC_NEED_RWLOCK
>> diff --git a/src/win32/thread.c b/src/win32/thread.c
>> index 9eb3db7..8d53185 100644
>> --- a/src/win32/thread.c
>> +++ b/src/win32/thread.c
>> @@ -96,15 +96,17 @@ static BOOL WINAPI
>> SleepConditionVariableFallback(CONDITION_VARIABLE *cv,
>>  /*** Mutexes ***/
>>  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. */
>>      InitializeCriticalSection (&p_mutex->mutex);
>> +    p_mutex->locked = 0;
>> +    p_mutex->b_recursive = false;
>>      p_mutex->dynamic = true;
>>  }
>>
>>  void vlc_mutex_init_recursive( vlc_mutex_t *p_mutex )
>>  {
>>      InitializeCriticalSection( &p_mutex->mutex );
>> +    p_mutex->locked = 0;
>> +    p_mutex->b_recursive = true;
>>      p_mutex->dynamic = true;
>>  }
>>
>> @@ -126,12 +128,14 @@ void vlc_mutex_lock (vlc_mutex_t *p_mutex)
>>              SleepConditionVariableCS(&super_variable, &super_mutex,
>> INFINITE);
>>              p_mutex->contention--;
>>          }
>> -        p_mutex->locked = true;
>> +        p_mutex->locked = 1;
>>          LeaveCriticalSection(&super_mutex);
>>          return;
>>      }
>>
>>      EnterCriticalSection (&p_mutex->mutex);
>> +    assert(!p_mutex->locked || p_mutex->b_recursive);
>> +    p_mutex->locked++;
>>  }
>>
>>  int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
>> @@ -143,14 +147,26 @@ int vlc_mutex_trylock (vlc_mutex_t *p_mutex)
>>          EnterCriticalSection(&super_mutex);
>>          if (!p_mutex->locked)
>>          {
>> -            p_mutex->locked = true;
>> +            p_mutex->locked = 1;
>>              ret = 0;
>>          }
>>          LeaveCriticalSection(&super_mutex);
>>          return ret;
>>      }
>>
>> -    return TryEnterCriticalSection (&p_mutex->mutex) ? 0 : EBUSY;
>> +    int ret = TryEnterCriticalSection (&p_mutex->mutex);
>> +    if (ret == 0)
>> +        return EBUSY;
>> +
>> +    assert(!p_mutex->locked || p_mutex->b_recursive);
>> +    if (unlikely(p_mutex->locked && !p_mutex->b_recursive))
>> +    {
>> +        LeaveCriticalSection (&p_mutex->mutex);
>> +        return EDEADLK; /* we already had the non-recursive lock */
>> +    }
>> +
>> +    p_mutex->locked++;
>> +    return 0;
>>  }
>>
>>  void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
>> @@ -159,13 +175,15 @@ void vlc_mutex_unlock (vlc_mutex_t *p_mutex)
>>      {   /* static mutexes */
>>          EnterCriticalSection(&super_mutex);
>>          assert (p_mutex->locked);
>> -        p_mutex->locked = false;
>> +        p_mutex->locked = 0;
>>          if (p_mutex->contention)
>>              WakeAllConditionVariable(&super_variable);
>>          LeaveCriticalSection(&super_mutex);
>>          return;
>>      }
>>
>> +    p_mutex->locked--;
>> +    assert(p_mutex->locked >= 0);
>>      LeaveCriticalSection (&p_mutex->mutex);
>>  }
>
>
> --
> Rémi Denis-Courmont
> http://www.remlab.net/
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel


More information about the vlc-devel mailing list