[2/2] kernel32: Implement InitOnceExecuteOnce() for Linux platform (resend)
Alexandre Julliard
julliard at winehq.org
Tue Jul 24 06:34:53 CDT 2012
Nikolay Sivov <nsivov at codeweavers.com> writes:
> +DWORD NTAPI RtlRunOnceExecuteOnce(PRTL_RUN_ONCE initonce, PRTL_RUN_ONCE_INIT_FN callback, void *parameter, void **ctxt)
> +{
> +#ifdef __linux__
> + if (!use_futexes()) return FALSE;
> +
> + for (;;)
> + {
> + DWORD_PTR val = (DWORD_PTR)interlocked_cmpxchg_ptr( &initonce->Ptr, (void*)1, NULL );
> + switch (val & 0x3)
> + {
> + case 0:
> + {
> + DWORD ret = callback(initonce, parameter, ctxt);
> + if (ret)
> + {
> + DWORD_PTR context = ctxt ? (DWORD_PTR)*ctxt : 0;
> + context = (context & ~0x3) | 0x2;
> + interlocked_cmpxchg_ptr( &initonce->Ptr, (void*)context, (void*)1 );
> + }
> + else
> + interlocked_cmpxchg_ptr( &initonce->Ptr, NULL, (void*)1 );
> + futex_wake( (int *)&initonce->Ptr, 1 );
> + return ret;
> + }
> + case 1:
> + /* blocked by another thread */
> + futex_wait( (int *)&initonce->Ptr, 1, NULL );
> + break;
> + case 2:
> + /* already initialized */
> + return TRUE;
> + }
> + }
It's supposed to return an NTSTATUS, not a boolean. Also you have to
always return the context, and you should try to do a generic
implementation first.
--
Alexandre Julliard
julliard at winehq.org
More information about the wine-devel
mailing list