[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