Web lists-archives.com

Re: [Mingw-users] GCC-4.9.3 is now our current release




Hi Ralph!

On Wed, Mar 16, 2016 at 1:50 PM, ralph engels <ralphengels@xxxxxxxxx> wrote:
> Yep thats the one :) the patch in question goes a little futher and
> checks for pthreads-w32 but else the idea is the same.
> Ill have a look at the differences might be your version is better.
>
> Still having random problems with thread lockup with pthreads-w32,
> at O3 optimiaztion it would lock up every time, at O2 it does less so
> but it still happens, not sure anything more can be done with compiler
> switches so it must be a regression somewhere in the library.

When I was playing around with this, I do not recall having trouble
with lockups.  However, I also do not recall compiling my baby test
programs with -O2 or -O3, so you've probably come across a real
problem that I wasn't thorough enough to detect.

> ,,,
> patch against thread here
>
> diff -urN gcc-5.3.0.old/libstdc++-v3/include/std/thread
> gcc-5.3.0/libstdc++-v3/include/std/thread
> --- gcc-5.3.0.old/libstdc++-v3/include/std/thread    2015-03-26
> 20:59:08.000000000 +0100
> +++ gcc-5.3.0/libstdc++-v3/include/std/thread    2016-03-15
> 23:05:54.288398100 +0100
> @@ -83,9 +83,26 @@
>         operator==(thread::id __x, thread::id __y) noexcept
>         { return __gthread_equal(__x._M_thread, __y._M_thread); }
>
> +      template<typename _Tp, typename = __void_t<>>
> +    struct __less
> +    {
> +      static bool
> +      _S_less(const _Tp& __x, const _Tp& __y)
> +      { return _GLIBCXX_THREAD_ID_LESS(__x, __y); }
> +    };
> +
> +      template<typename _Tp>
> +    struct __less<_Tp, __void_t<decltype(std::declval<const _Tp&>()
> +                         < std::declval<const _Tp&>())>>
> +    {
> +      static bool
> +      _S_less(const _Tp& __x, const _Tp& __y)
> +      { return __x < __y; }
> +    };
> +
>         friend bool
>         operator<(thread::id __x, thread::id __y) noexcept
> -      { return __x._M_thread < __y._M_thread; }
> +      {    return __less<native_handle_type>::_S_less(__x._M_thread,
> __y._M_thread); }

When I try to parse this in my head, I conclude that __less gets
instantiated as the _GLIBCXX_THREAD_ID_LESS version:

      static bool
      _S_less(const _Tp& __x, const _Tp& __y)
      { return _GLIBCXX_THREAD_ID_LESS(__x, __y); }

(Is this true?)

> ...
> and the check for pthreads-w32  here
>
> diff -urN gcc-5.3.0.old/libstdc++-v3/config/os/mingw32/os_defines.h
> gcc-5.3.0/libstdc++-v3/config/os/mingw32/os_defines.h
> --- gcc-5.3.0.old/libstdc++-v3/config/os/mingw32/os_defines.h 2015-01-05
> 13:33:28.000000000 +0100
> +++ gcc-5.3.0/libstdc++-v3/config/os/mingw32/os_defines.h 2016-03-15
> 23:02:55.988148500 +0100
> @@ -78,4 +78,11 @@
>   // See libstdc++/59807
>   #define _GTHREAD_USE_MUTEX_INIT_FUNC 1
>
> +#ifdef PTW32_VERSION
> +// See libstdc++/67114
> +# ifndef _GLIBCXX_THREAD_ID_LESS
> +#  define _GLIBCXX_THREAD_ID_LESS(X, Y) ((X).x < (Y).x)

This looks fishy to me, assuming that the ptw32_handle_t struct hasn't
changed significantly from five years ago:

   typedef struct {
       void * p;                   /* Pointer to actual object */
       unsigned int x;             /* Extra information - reuse count etc */
   } ptw32_handle_t;

I have not tracked down what these data members actually are,
but I assume that p is a pointer to (a wrapper around) a native
thread, and that x is some subsidiary information (that possibly
changes during the lifetime of the thread).

It seems to me that two different threads could have the same
value of x and therefore have both  X < Y  and  Y < X  be false,
which seems wrong.

(I don't know if operator< for thread::id (maps to ptw32_handle_t)
is used internally anywhere, so I don't know if this would break
anything.  But the standard requires that operator< (and operator==
and others) be defined for thread::id, and I think your version of
_GLIBCXX_THREAD_ID_LESS gives wrong and inconsistent
behavior.)

My gut told me to have operator< resolve to  X.p < Y.p  (on the
theory that p is a pointer to a nice, unique thread object in memory)
but the existing code has operator== defined in terms of
__gthread_equal which resolves (in my old version) to pthread_equal:

   pthread_equal (pthread_t t1, pthread_t t2)
   {
     int result;
     result = ( t1.p == t2.p && t1.x == t2.x );
     return (result);
   }

which requires equality not only of p, but of x, as well.  This is why
I implemented operator< in terms of first p and then x:

      friend bool
      operator<(thread::id __x, thread::id __y)
      { return ( (__x._M_thread.p < __y._M_thread.p)  ||  (
(__x._M_thread.p == __y._M_thread.p) && (__x._M_thread.x <
__y._M_thread.x) ) ); }

Again, I don't know what x is for, so I don't know whether this matters,
but the mathematician in me wants operator== and operator< to be
consistent (in that  X == Y  if, and only if both  X < Y  and  Y < X
are false), and my version of operator< achieves this.

> ...
> Regards Ralph Engels.


Happy pthread / std::thread Hacking!


K. Frank

------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785231&iu=/4140
_______________________________________________
MinGW-users mailing list
MinGW-users@xxxxxxxxxxxxxxxxxxxxx

This list observes the Etiquette found at 
http://www.mingw.org/Mailing_Lists.
We ask that you be polite and do the same.  Disregard for the list etiquette may cause your account to be moderated.

_______________________________________________
You may change your MinGW Account Options or unsubscribe at:
https://lists.sourceforge.net/lists/listinfo/mingw-users
Also: mailto:mingw-users-request@xxxxxxxxxxxxxxxxxxxxx?subject=unsubscribe