[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