multithreading broken in Cygwin 3.5.3
Bruno Haible
bruno@clisp.org
Wed May 29 11:29:04 GMT 2024
Takashi Yano wrote:
> > My workaround implementation of pthread_once (in gnulib) looks like this:
> >
> > /* This would be the code, for
> > typedef struct
> > {
> > pthread_mutex_t mutex;
> > _Atomic unsigned int num_threads;
> > _Atomic unsigned int done;
> > }
> > pthread_once_t;
> > */
> > if (once_control->done == 0)
> > {
> > once_control->num_threads += 1;
> > pthread_mutex_lock (&once_control->mutex);
> > if (once_control->done == 0)
> > {
> > (*initfunction) ();
> > once_control->done = 1;
> > }
> > pthread_mutex_unlock (&once_control->mutex);
> > if ((once_control->num_threads -= 1) == 0)
> > pthread_mutex_destroy (&once_control->mutex);
> > }
> >
> > It makes sure that
> > - The last thread that had been dealing with the mutex deletes
> > the mutex.
> > - Once the mutex is deleted, is it never again accessed. The
> > entry test of the 'done' boolean ensures this.
>
> Thanks for the advice.
>
> The problem is that we cannot change the type of pthread_once_t
> for binary compatibility. My patch stops to use
> pthread_mutex_t mutex in pthread_once_t however it cannot be
> deleted despite it is not used at all.
This problem can be solved, by using
- the upper 31 bits of 'state' as 'num_threads' and
- the lowest bit of 'state' as 'done' bit.
I did this in gnulib:
https://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/pthread-once.c;h=069e77e3f3fc2a6e6564f73ba1a3f86ddf9ba531;hb=HEAD#l41
and I have tested it with the test program 'test-pthread-once2' that
I mentioned in my original report.
You can take this code, since I licensed it under LGPLv2+. You can
also surely simplify it, since you are an expert with the Interlocked*
atomic operations (whereas I only wanted to use the GCC built-in
__sync* atomics).
Bruno
More information about the Cygwin
mailing list