syphilis has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

https://winlibs.com is a good source of mingw-w64 toolchains.
Currently, their compilers provide threading via pthreads, but they are planning to move to mcf threads.
That shouldn't be a big issue - the experimental 64-bit mcf toolchain that they've just provided builds perl straight out of the box, with all tests passing. (Not so with the 32-bit mcf compiler, but I would think that can be fixed inside the perl source.)

However, I was puzzled by a change in behaviour of the following script and, being a complete idiot wrt threading, I'm keen to hear thoughts from those who know about threads.
(FAIK, my script might be rubbish that is triggering undefined or implementation-dependent behaviour).
Here is the script:
use warnings; use strict; use threads; use Math::MPFR qw(:mpfr); die "threads version is too old" if $threads::VERSION < 1.71; die "mpfr library was built without TLS support" unless Rmpfr_buildopt_tls_p(); # Default precision is 53. # First, change it to 101 # Then change it to 201 (inside a separate thread) Rmpfr_set_default_prec(101); my $thr1 = threads->create( sub { Rmpfr_set_default_prec(201); return Rmpfr_get_default_prec(); } ); my $res = $thr1->join(); if($res == 201) { print "ok 1\n" } else { print "\$res: $res (expected 201) not ok 1\n" } if(Rmpfr_get_default_prec() == 101) { print "ok 2\n" } else { print "\$res: $res\nprec: ", Rmpfr_get_default_prec(), "\nNOT o +k 2\n"}
When perl is built with the mcf toolchain I get:
>perl tls.pl $res: 53 (expected 201) not ok 1 ok 2
When perl is built with the pthreads toolchain (or built on Linux) I get:
>perl tls.pl ok 1 ok 2
The only difference lies in the compiler that built perl.
Other than that, it's the same perl source, same Math::MPFR source and the same static mpfr and gmp libraries.
The Rmpfr_set_default_prec() function is a wrapper around the mpfr function that sets the default precision (in bits) in the mpfr library. Initial (default) precision is 53.
And the Rmpfr_get_default_prec() function is a wrapper around the mpfr function that returns that default precision.

Thoughts ?
It seems odd that, having passed the plethora of "threads" tests in perl's test suite, the "mcf" build should stumble on such a basic script.

Cheers,
Rob

Replies are listed 'Best First'.
Re: [Win32] differing threads behaviour
by syphilis (Archbishop) on Apr 09, 2023 at 01:21 UTC
    Thoughts ?

    Duh ... anyone with half a brain would probably be sceptical that MCF threads are going to just magically work with perl without any need to modify the perl source.
    The fact that my "mcf" build has a runtime dependency on libmcfgthread-1.dll was enough to fool me - but I think that my "mcf" build might very well be a "pthreads" one, and the difference I'm seeing is the result of a change between gcc-12.2.0 and gcc-13.0.1.

    I'll work on reproducing the difference in a C program and take it up with the appropriate body.

    Cheers,
    Rob
      I'll work on reproducing the difference in a C program and take it up with the appropriate body.

      I've arrived at:
      #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <mpfr.h> void *foo( void *ptr ); int main(void) { pthread_t thread1; char *message1 = "precision in thread1:"; int iret1; if(mpfr_buildopt_tls_p()) printf("mpfr was built with TLS support +\n"); else printf("mpfr was NOT built with TLS support\n"); mpfr_set_default_prec(101); iret1 = pthread_create( &thread1, NULL, foo, (void*) message1); pthread_join( thread1, NULL); printf("pthread_create() returned: %d\n",iret1); printf("Back in main: %d\n", mpfr_get_default_prec()); return 0; } void *foo( void * ptr) { char *message; message = (char *) ptr; mpfr_set_default_prec(201); printf("%s %d\n", message, mpfr_get_default_prec()); pthread_exit (NULL); }
      It exhibits the same 12.2.0-versus-13.0.l anomaly.
      If that C program is compiled using gcc-12.2.0, then the foo() sub reports that default precision is 201, but if it's compiled using gcc-13.0.1 then a default precision of 53 is reported.
      According to the mpfr developers, it should report 201.
      I'll see if I can get the mingw-w64 developers to shed some light on what's going awry.

      Cheers,
      Rob
        I'll see if I can get the mingw-w64 developers to shed some light on what's going awry.

        Liu Hao (lh_mouse) has provided the following explanation:
        It's because `__emutls_get_address()` returns two distinct values in c +onsecutive calls with the same descriptor in the same thread, so the second reference to the thread l +ocal `__gmpfr_default_fp_bit_precision` (defined in 'set_dfl_prec.c') gets +a fresh object with its default value.
        The "second reference" is the mpfr_get_default() call made in foo().
        He then followed that up with:
        Looks like emutls could not set the thread-specific value for 'foreign + threads' (those not created by mcfgthread). Although this is by design, I do think the MPFR expect +ation should be reasonably supported. I will fix this in a couple of days.
        Entire thread is at:
        https://sourceforge.net/p/mingw-w64/mailman/mingw-w64-public/thread/3a656408-a99f-e9c1-e4f0-c4ff8374bb30%40126.com/#msg37802424

        Here endeth this soliloquy ;-)

        Cheers,
        Rob