[FFmpeg-devel] [PATCH] w32pthreads: add pthread_once emulation

Matt Oliver protogonoi at gmail.com
Wed Oct 7 18:23:15 CEST 2015


On 6 October 2015 at 21:36, Hendrik Leppkes <h.leppkes at gmail.com> wrote:

> The emulation uses native InitOnce* APIs on Windows Vista+, and a
> lock-free/allocation-free approach using atomics and spinning for Windows
> XP.
> ---
>
> This is in preparation to use pthread_once for global static init
> functions,
> and eventually removing the global lock in avcodec_open2
>
> compat/w32pthreads.h | 68
> ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 68 insertions(+)
>
> diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h
> index deb1c53..8523976 100644
> --- a/compat/w32pthreads.h
> +++ b/compat/w32pthreads.h
> @@ -154,6 +154,19 @@ static inline int pthread_cond_signal(pthread_cond_t
> *cond)
>      return 0;
>  }
>
> +typedef INIT_ONCE pthread_once_t;
> +#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
> +
> +static av_unused int pthread_once(pthread_once_t *once_control, void
> (*init_routine)(void))
> +{
> +    BOOL pending = FALSE;
> +    InitOnceBeginInitialize(once_control, 0, &pending, NULL);
> +    if (pending)
> +        init_routine();
> +    InitOnceComplete(once_control, 0, NULL);
> +    return 0;
> +}
> +
>  #else // _WIN32_WINNT < 0x0600
>  /* for pre-Windows 6.0 platforms we need to define and use our own
> condition
>   * variable and api */
> @@ -304,6 +317,57 @@ static av_unused int
> pthread_cond_signal(pthread_cond_t *cond)
>      pthread_mutex_unlock(&win32_cond->mtx_broadcast);
>      return 0;
>  }
> +
> +/* for pre-Windows 6.0 platforms, define INIT_ONCE struct,
> + * compatible to the one used in the native API */
> +
> +typedef union pthread_once_t  {
> +    void * Ptr;    ///< For the Windows 6.0+ native functions
> +    LONG state;    ///< For the pre-Windows 6.0 compat code
> +} pthread_once_t;
> +
> +#define PTHREAD_ONCE_INIT {0}
> +
> +/* function pointers to init once API on windows 6.0+ kernels */
> +static BOOL (WINAPI *initonce_begin)(pthread_once_t *lpInitOnce, DWORD
> dwFlags, BOOL *fPending, void **lpContext);
> +static BOOL (WINAPI *initonce_complete)(pthread_once_t *lpInitOnce, DWORD
> dwFlags, void *lpContext);
> +
> +static av_unused int pthread_once(pthread_once_t *once_control, void
> (*init_routine)(void))
> +{
> +    /* Use native functions on Windows 6.0+ */
> +    if (initonce_begin && initonce_complete)
> +    {
> +        BOOL pending = FALSE;
> +        initonce_begin(once_control, 0, &pending, NULL);
> +        if (pending)
> +            init_routine();
> +        initonce_complete(once_control, 0, NULL);
> +        return 0;
> +    }
> +
> +    /* pre-Windows 6.0 compat using a spin-lock */
> +    switch (InterlockedCompareExchange(&once_control->state, 1, 0))
> +    {
> +        /* Initial run */
> +        case 0:
> +            init_routine();
> +            InterlockedExchange(&once_control->state, 2);
> +            break;
> +        /* Another thread is running init */
> +        case 1:
> +            while (1) {
> +                MemoryBarrier();
> +                if (once_control->state == 2)
> +                    break;
> +                Sleep(0);
> +            }
> +            break;
> +        /* Initialization complete */
> +        case 2:
> +            break;
> +    }
> +    return 0;
> +}
>  #endif
>
>  static av_unused void w32thread_init(void)
> @@ -319,6 +383,10 @@ static av_unused void w32thread_init(void)
>          (void*)GetProcAddress(kernel_dll, "WakeConditionVariable");
>      cond_wait      =
>          (void*)GetProcAddress(kernel_dll, "SleepConditionVariableCS");
> +    initonce_begin =
> +        (void*)GetProcAddress(kernel_dll, "InitOnceBeginInitialize");
> +    initonce_complete =
> +        (void*)GetProcAddress(kernel_dll, "InitOnceComplete");
>  #endif
>
>  }
> --
> 2.5.3.windows.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


LGTM


More information about the ffmpeg-devel mailing list