On 8 October 2015 at 04:15, Hendrik Leppkes <h.lepp...@gmail.com> wrote:
> On Wed, Oct 7, 2015 at 7:06 PM, Matt Oliver <protogo...@gmail.com> wrote: > > On 8 October 2015 at 03:29, Hendrik Leppkes <h.lepp...@gmail.com> wrote: > > > >> On Wed, Oct 7, 2015 at 6:23 PM, Matt Oliver <protogo...@gmail.com> > wrote: > >> > On 6 October 2015 at 21:36, Hendrik Leppkes <h.lepp...@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 > >> > > >> > > >> > LGTM > >> > >> There is a new version of the patch which also solves the > >> w32thread_init mess, so this one isn't the final version anymore. > >> Current working version is here: > >> https://github.com/Nevcairiel/FFmpeg/commits/pthread_once > >> > >> > > This looks better. > > So by win32thread_init mess im assuming your referring to a need to have > > called it before hand. Given that youve added it to the only 2 functions > > that need it then doesnt that mean that win32thread_init be completely > > removed from all other code and only used locally in w32pthread.h and > only > > when WIN32_WINNT<0x600. > > Yes, it can be removed in a follow up commit. OK, I was just checking if that was the plan or not. Looks good to me. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel