[PATCH v2] Cygwin: pthread: Fix a race issue introduced by the commit 2c5433e5da82
Bruno Haible
bruno@clisp.org
Sun Jun 2 13:14:51 GMT 2024
Hi Takashi Yano,
> The result is as follows (submitted as v4 patch).
>
> int
> pthread::once (pthread_once_t *once_control, void (*init_routine) (void))
> {
> /* Sign bit of once_control->state is used as done flag.
> Similary, the next significant bit is used as destroyed flag. */
> const int done = INT_MIN; /* 0b1000000000000000 */
> const int destroyed = INT_MIN >> 1; /* 0b1100000000000000 */
> if (once_control->state & done)
> return 0;
>
> /* The type of &once_control->state is int *, which is compatible with
> LONG * (the type of the pointer argument of InterlockedXxx()). */
> if ((InterlockedIncrement (&once_control->state) & done) == 0)
> {
> pthread_mutex_lock (&once_control->mutex);
> if (!(once_control->state & done))
> {
> init_routine ();
> InterlockedOr (&once_control->state, done);
> }
> pthread_mutex_unlock (&once_control->mutex);
> }
> InterlockedDecrement (&once_control->state);
> if (InterlockedCompareExchange (&once_control->state,
> destroyed, done) == done)
> pthread_mutex_destroy (&once_control->mutex);
> return 0;
> }
> ...
> I believe both codes are equivalent. Could you please check?
Yes, they are equivalent. This code is free of race conditions. (Let's
hope I am not making a mistake again.)
For legibility I would write the constant values as bit masks:
0x80000000
0xc0000000
and - following the habit that constant integers should have names in
upper case - I would rename
done → DONE
destroyed → DESTROYED
Bruno
More information about the Cygwin
mailing list