Re: realpath() patch to fix symlinks resolution for win32

2023-02-10 Thread i.nixman--- via Gcc-patches

On 2023-02-11 06:32, Jonathan Yong wrote:

On 2/6/23 06:40, Jonathan Yong wrote:

On 1/18/23 10:44, i.nixman--- via Gcc-patches wrote:

hello again!

the final version of the path for 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350


successfully bootstraped for x86_64-mingw32 and x86_64-linux.

could anyone apply it please?



best!


Looks good to me, please supply the appropriate changelog.


Pushed to master.



Thank you Jonathan!

could you please close the corresponding BR too?:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350



best!


Re: realpath() patch to fix symlinks resolution for win32

2023-01-26 Thread i.nixman--- via Gcc-patches



hello,

could someone look at patch attached please?

https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610147.html


Re: libquadmath fix for 94756 and 87204

2023-01-26 Thread i.nixman--- via Gcc-patches

hello,

could someone look at the patch attached please?

https://gcc.gnu.org/pipermail/gcc-patches/2023-January/610392.html


Re: libquadmath fix for 94756 and 87204

2023-01-21 Thread i.nixman--- via Gcc-patches


hello Jakub,


The above looks way too complicated for what it does.
If all you want to change mp_limb* to be long long for mingw 64-bit,
then just do:


done.




Why?


could you explain which of the nine lines are you talking about?



As for the rest, it would help if you could list the exact glibc 
commits

which you've ported to libquadmath and indicate if it is solely those
and nothing else.


I'm sorry but it was not my intention to remember exactly which commits 
I was looking at...

I didn't think about it.




The patch needs a ChangeLog entry too.


done.



the patch in attachments.
From 1d096d1c002533a1685599fd7f8b1ef506aae674 Mon Sep 17 00:00:00 2001
From: niXman 
Date: Sat, 21 Jan 2023 18:15:23 +0200
Subject: [PATCH] used type for MinGW target for x86_64 & the overflow
 described on BugZilla 94756 was fixed

---
 libquadmath/printf/gmp-impl.h | 25 +
 libquadmath/strtod/strtod_l.c | 29 +
 2 files changed, 34 insertions(+), 20 deletions(-)

diff --git a/libquadmath/printf/gmp-impl.h b/libquadmath/printf/gmp-impl.h
index 94d88efc57f..b7f8e70f5b1 100644
--- a/libquadmath/printf/gmp-impl.h
+++ b/libquadmath/printf/gmp-impl.h
@@ -33,15 +33,24 @@ MA 02111-1307, USA. */
 #define MAX(h,i) ((h) > (i) ? (h) : (i))
 #endif
 
-#define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
-#define BYTES_PER_MP_LIMB (BITS_PER_MP_LIMB / __CHAR_BIT__)
-typedef unsigned long int	mp_limb_t;
-typedef long int		mp_limb_signed_t;
+#ifdef __MINGW32__ && defined(__x86_64__)
+  /* for MinGW targets the Microsoft ABI requires that `long`
+ type will always have 32 bit, because of that we will use
+ `long long` for MinGW on 64-bit builds */
+  typedef  long long int mp_limb_signed_t;
+  typedef unsigned long long int mp_limb_t;
+# define BITS_PER_MP_LIMB (__SIZEOF_LONG_LONG__ * __CHAR_BIT__)
+#else // !__MINGW32__
+  typedef  long int mp_limb_signed_t;
+  typedef unsigned long int mp_limb_t;
+# define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
+#endif // __MINGW32__
 
-typedef mp_limb_t * mp_ptr;
-typedef const mp_limb_t *	mp_srcptr;
-typedef long intmp_size_t;
-typedef long intmp_exp_t;
+#define BYTES_PER_MP_LIMB (BITS_PER_MP_LIMB / __CHAR_BIT__)
+typedef mp_limb_t*mp_ptr;
+typedef const mp_limb_t  *mp_srcptr;
+typedef long int  mp_size_t;
+typedef long int  mp_exp_t;
 
 /* Define stuff for longlong.h.  */
 typedef unsigned int UQItype	__attribute__ ((mode (QI)));
diff --git a/libquadmath/strtod/strtod_l.c b/libquadmath/strtod/strtod_l.c
index 0b0e85a3cf7..6790124e6fc 100644
--- a/libquadmath/strtod/strtod_l.c
+++ b/libquadmath/strtod/strtod_l.c
@@ -200,7 +200,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 
 	  round_limb = retval[RETURN_LIMB_SIZE - 1];
 	  round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
-	  for (i = 0; i < RETURN_LIMB_SIZE; ++i)
+	  for (i = 0; i < RETURN_LIMB_SIZE - 1; ++i)
 	more_bits |= retval[i] != 0;
 	  MPN_ZERO (retval, RETURN_LIMB_SIZE);
 	}
@@ -215,9 +215,14 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 	  more_bits |= ((round_limb & mp_limb_t) 1) << round_bit) - 1))
 			!= 0);
 
-	  (void) mpn_rshift (retval, [shift / BITS_PER_MP_LIMB],
-			 RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
-			 shift % BITS_PER_MP_LIMB);
+/* mpn_rshift requires 0 < shift < BITS_PER_MP_LIMB.  */
+if ((shift % BITS_PER_MP_LIMB) != 0)
+  (void) mpn_rshift (retval, [shift / BITS_PER_MP_LIMB],
+  RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
+  shift % BITS_PER_MP_LIMB);
+else
+  for (i = 0; i < RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB); i++)
+retval[i] = retval[i + (shift / BITS_PER_MP_LIMB)];
 	  MPN_ZERO ([RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
 		shift / BITS_PER_MP_LIMB);
 	}
@@ -276,7 +281,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 	}
 }
 
-  if (exponent > MAX_EXP)
+  if (exponent >= MAX_EXP)
 goto overflow;
 
 #ifdef HAVE_FENV_H
@@ -308,7 +313,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 }
 #endif
 
-  if (exponent > MAX_EXP)
+  if (exponent >= MAX_EXP)
   overflow:
 return overflow_value (negative);
 
@@ -688,7 +693,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
 	  if (endptr != NULL)
 	*endptr = (STRING_TYPE *) cp;
 
-	  return retval;
+	  return negative ? -retval : retval;
 	}
 
   /* It is really a text we do not recognize.  */
@@ -1193,7 +1198,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
   if (__builtin_expect (exponent > MAX_10_EXP + 1 - (intmax_t) int_no, 0))
 return overflow_value (negative);
 
-  if (__builtin_expect (exponent < MIN_10_EXP - (DIG + 1), 0))
+  if (__builtin_expect (exponent < MIN_10_EXP - (DIG + 2), 0))
 return underflow_value (negative);
 

Re: libquadmath fix for 94756 and 87204

2023-01-20 Thread i.nixman--- via Gcc-patches

updated path.
only the comment has been corrected.
diff --git a/libquadmath/printf/gmp-impl.h b/libquadmath/printf/gmp-impl.h
index 94d88efc57f..af0719321dc 100644
--- a/libquadmath/printf/gmp-impl.h
+++ b/libquadmath/printf/gmp-impl.h
@@ -33,15 +33,30 @@ MA 02111-1307, USA. */
 #define MAX(h,i) ((h) > (i) ? (h) : (i))
 #endif
 
-#define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
-#define BYTES_PER_MP_LIMB (BITS_PER_MP_LIMB / __CHAR_BIT__)
-typedef unsigned long int	mp_limb_t;
-typedef long int		mp_limb_signed_t;
+#ifdef __MINGW32__
+  /* for MinGW targets the Microsoft ABI requires `long`
+ type will always have 32 bit, because of that we will use
+ `long` for 32-bit builds and `long long` for 64-bit builds */
+# if __x86_64__
+   typedef  long long int mp_limb_signed_t;
+   typedef unsigned long long int mp_limb_t;
+#  define BITS_PER_MP_LIMB (__SIZEOF_LONG_LONG__ * __CHAR_BIT__)
+# else // !__x86_64__
+   typedef  long int mp_limb_signed_t;
+   typedef unsigned long int mp_limb_t;
+#  define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
+# endif // __x86_64__
+#else // !__MINGW32__
+  typedef  long int mp_limb_signed_t;
+  typedef unsigned long int mp_limb_t;
+# define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
+#endif // __MINGW32__
 
-typedef mp_limb_t * mp_ptr;
-typedef const mp_limb_t *	mp_srcptr;
-typedef long intmp_size_t;
-typedef long intmp_exp_t;
+#define BYTES_PER_MP_LIMB (BITS_PER_MP_LIMB / __CHAR_BIT__)
+typedef long int  mp_size_t;
+typedef long int  mp_exp_t;
+typedef mp_limb_t*mp_ptr;
+typedef const mp_limb_t  *mp_srcptr;
 
 /* Define stuff for longlong.h.  */
 typedef unsigned int UQItype	__attribute__ ((mode (QI)));
diff --git a/libquadmath/strtod/strtod_l.c b/libquadmath/strtod/strtod_l.c
index 0b0e85a3cf7..6790124e6fc 100644
--- a/libquadmath/strtod/strtod_l.c
+++ b/libquadmath/strtod/strtod_l.c
@@ -200,7 +200,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 
 	  round_limb = retval[RETURN_LIMB_SIZE - 1];
 	  round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
-	  for (i = 0; i < RETURN_LIMB_SIZE; ++i)
+	  for (i = 0; i < RETURN_LIMB_SIZE - 1; ++i)
 	more_bits |= retval[i] != 0;
 	  MPN_ZERO (retval, RETURN_LIMB_SIZE);
 	}
@@ -215,9 +215,14 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 	  more_bits |= ((round_limb & mp_limb_t) 1) << round_bit) - 1))
 			!= 0);
 
-	  (void) mpn_rshift (retval, [shift / BITS_PER_MP_LIMB],
-			 RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
-			 shift % BITS_PER_MP_LIMB);
+/* mpn_rshift requires 0 < shift < BITS_PER_MP_LIMB.  */
+if ((shift % BITS_PER_MP_LIMB) != 0)
+  (void) mpn_rshift (retval, [shift / BITS_PER_MP_LIMB],
+  RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
+  shift % BITS_PER_MP_LIMB);
+else
+  for (i = 0; i < RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB); i++)
+retval[i] = retval[i + (shift / BITS_PER_MP_LIMB)];
 	  MPN_ZERO ([RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
 		shift / BITS_PER_MP_LIMB);
 	}
@@ -276,7 +281,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 	}
 }
 
-  if (exponent > MAX_EXP)
+  if (exponent >= MAX_EXP)
 goto overflow;
 
 #ifdef HAVE_FENV_H
@@ -308,7 +313,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 }
 #endif
 
-  if (exponent > MAX_EXP)
+  if (exponent >= MAX_EXP)
   overflow:
 return overflow_value (negative);
 
@@ -688,7 +693,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
 	  if (endptr != NULL)
 	*endptr = (STRING_TYPE *) cp;
 
-	  return retval;
+	  return negative ? -retval : retval;
 	}
 
   /* It is really a text we do not recognize.  */
@@ -1193,7 +1198,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
   if (__builtin_expect (exponent > MAX_10_EXP + 1 - (intmax_t) int_no, 0))
 return overflow_value (negative);
 
-  if (__builtin_expect (exponent < MIN_10_EXP - (DIG + 1), 0))
+  if (__builtin_expect (exponent < MIN_10_EXP - (DIG + 2), 0))
 return underflow_value (negative);
 
   if (int_no > 0)
@@ -1360,7 +1365,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
 
 assert (dig_no > int_no
 	&& exponent <= 0
-	&& exponent >= MIN_10_EXP - (DIG + 1));
+	&& exponent >= MIN_10_EXP - (DIG + 2));
 
 /* We need to compute MANT_DIG - BITS fractional bits that lie
within the mantissa of the result, the following bit for
@@ -1651,8 +1656,8 @@ STRTOF_INTERNAL (nptr, endptr, group)
 	  d1 = den[densize - 2];
 
 	  /* The division does not work if the upper limb of the two-limb
-	 numerator is greater than the denominator.  */
-	  if (mpn_cmp (num, [densize - numsize], numsize) > 0)
+	 numerator is greater or equal to than the denominator.  */
+	  if (mpn_cmp (num, [densize - numsize], numsize) >= 0)
 	

libquadmath fix for 94756 and 87204

2023-01-20 Thread i.nixman--- via Gcc-patches

hello,

I have fixed:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94756
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87204

tested on i686-mingw-w64, x86_64-mingw-w64, and for i686 and x86_64 
linux.


could anyone check and apply please?



best!
diff --git a/libquadmath/printf/gmp-impl.h b/libquadmath/printf/gmp-impl.h
index 94d88efc57f..af0719321dc 100644
--- a/libquadmath/printf/gmp-impl.h
+++ b/libquadmath/printf/gmp-impl.h
@@ -33,15 +33,30 @@ MA 02111-1307, USA. */
 #define MAX(h,i) ((h) > (i) ? (h) : (i))
 #endif
 
-#define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
-#define BYTES_PER_MP_LIMB (BITS_PER_MP_LIMB / __CHAR_BIT__)
-typedef unsigned long int	mp_limb_t;
-typedef long int		mp_limb_signed_t;
+#ifdef __MINGW32__
+  /* for MinGW targets the Microsoft ABI requires that `long`
+ types will always have 32 bit, because of that we will use
+ `int32_t` for 32-bit builds and `int64_t` for 64-bit builds */
+# if __x86_64__
+   typedef  long long int mp_limb_signed_t;
+   typedef unsigned long long int mp_limb_t;
+#  define BITS_PER_MP_LIMB (__SIZEOF_LONG_LONG__ * __CHAR_BIT__)
+# else // !__x86_64__
+   typedef  long int mp_limb_signed_t;
+   typedef unsigned long int mp_limb_t;
+#  define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
+# endif // __x86_64__
+#else // !__MINGW32__
+  typedef  long int mp_limb_signed_t;
+  typedef unsigned long int mp_limb_t;
+# define BITS_PER_MP_LIMB (__SIZEOF_LONG__ * __CHAR_BIT__)
+#endif // __MINGW32__
 
-typedef mp_limb_t * mp_ptr;
-typedef const mp_limb_t *	mp_srcptr;
-typedef long intmp_size_t;
-typedef long intmp_exp_t;
+#define BYTES_PER_MP_LIMB (BITS_PER_MP_LIMB / __CHAR_BIT__)
+typedef long int  mp_size_t;
+typedef long int  mp_exp_t;
+typedef mp_limb_t*mp_ptr;
+typedef const mp_limb_t  *mp_srcptr;
 
 /* Define stuff for longlong.h.  */
 typedef unsigned int UQItype	__attribute__ ((mode (QI)));
diff --git a/libquadmath/strtod/strtod_l.c b/libquadmath/strtod/strtod_l.c
index 0b0e85a3cf7..6790124e6fc 100644
--- a/libquadmath/strtod/strtod_l.c
+++ b/libquadmath/strtod/strtod_l.c
@@ -200,7 +200,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 
 	  round_limb = retval[RETURN_LIMB_SIZE - 1];
 	  round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB;
-	  for (i = 0; i < RETURN_LIMB_SIZE; ++i)
+	  for (i = 0; i < RETURN_LIMB_SIZE - 1; ++i)
 	more_bits |= retval[i] != 0;
 	  MPN_ZERO (retval, RETURN_LIMB_SIZE);
 	}
@@ -215,9 +215,14 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 	  more_bits |= ((round_limb & mp_limb_t) 1) << round_bit) - 1))
 			!= 0);
 
-	  (void) mpn_rshift (retval, [shift / BITS_PER_MP_LIMB],
-			 RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
-			 shift % BITS_PER_MP_LIMB);
+/* mpn_rshift requires 0 < shift < BITS_PER_MP_LIMB.  */
+if ((shift % BITS_PER_MP_LIMB) != 0)
+  (void) mpn_rshift (retval, [shift / BITS_PER_MP_LIMB],
+  RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB),
+  shift % BITS_PER_MP_LIMB);
+else
+  for (i = 0; i < RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB); i++)
+retval[i] = retval[i + (shift / BITS_PER_MP_LIMB)];
 	  MPN_ZERO ([RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)],
 		shift / BITS_PER_MP_LIMB);
 	}
@@ -276,7 +281,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 	}
 }
 
-  if (exponent > MAX_EXP)
+  if (exponent >= MAX_EXP)
 goto overflow;
 
 #ifdef HAVE_FENV_H
@@ -308,7 +313,7 @@ round_and_return (mp_limb_t *retval, intmax_t exponent, int negative,
 }
 #endif
 
-  if (exponent > MAX_EXP)
+  if (exponent >= MAX_EXP)
   overflow:
 return overflow_value (negative);
 
@@ -688,7 +693,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
 	  if (endptr != NULL)
 	*endptr = (STRING_TYPE *) cp;
 
-	  return retval;
+	  return negative ? -retval : retval;
 	}
 
   /* It is really a text we do not recognize.  */
@@ -1193,7 +1198,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
   if (__builtin_expect (exponent > MAX_10_EXP + 1 - (intmax_t) int_no, 0))
 return overflow_value (negative);
 
-  if (__builtin_expect (exponent < MIN_10_EXP - (DIG + 1), 0))
+  if (__builtin_expect (exponent < MIN_10_EXP - (DIG + 2), 0))
 return underflow_value (negative);
 
   if (int_no > 0)
@@ -1360,7 +1365,7 @@ STRTOF_INTERNAL (nptr, endptr, group)
 
 assert (dig_no > int_no
 	&& exponent <= 0
-	&& exponent >= MIN_10_EXP - (DIG + 1));
+	&& exponent >= MIN_10_EXP - (DIG + 2));
 
 /* We need to compute MANT_DIG - BITS fractional bits that lie
within the mantissa of the result, the following bit for
@@ -1651,8 +1656,8 @@ STRTOF_INTERNAL (nptr, endptr, group)
 	  d1 = den[densize - 2];
 
 	  /* The division does not work if the upper limb of the two-limb
-	 numerator is greater 

realpath() patch to fix symlinks resolution for win32

2023-01-18 Thread i.nixman--- via Gcc-patches

hello again!

the final version of the path for 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350


successfully bootstraped for x86_64-mingw32 and x86_64-linux.

could anyone apply it please?



best!
diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c
index 3c7053b0b70..a1ad074d00e 100644
--- a/libiberty/lrealpath.c
+++ b/libiberty/lrealpath.c
@@ -68,8 +68,135 @@ extern char *canonicalize_file_name (const char *);
   /* cygwin has realpath, so it won't get here.  */ 
 # if defined (_WIN32)
 #  define WIN32_LEAN_AND_MEAN
-#  include  /* for GetFullPathName */
-# endif
+#  include  /* for GetFullPathName/GetFinalPathNameByHandle/
+  CreateFile/CloseHandle */
+#  define WIN32_REPLACE_SLASHES(_ptr, _len) \
+ for (unsigned i = 0; i != (_len); ++i) \
+   if ((_ptr)[i] == '\\') (_ptr)[i] = '/';
+
+#  define WIN32_UNC_PREFIX "//?/UNC/"
+#  define WIN32_UNC_PREFIX_LEN (sizeof(WIN32_UNC_PREFIX)-1)
+#  define WIN32_IS_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_UNC_PREFIX, WIN32_UNC_PREFIX_LEN))
+
+#  define WIN32_NON_UNC_PREFIX "//?/"
+#  define WIN32_NON_UNC_PREFIX_LEN (sizeof(WIN32_NON_UNC_PREFIX)-1)
+#  define WIN32_IS_NON_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_NON_UNC_PREFIX, WIN32_NON_UNC_PREFIX_LEN))
+
+/* Get full path name without symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_full_path_name(const char *filename) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+ from the man: `If the lpBuffer buffer is too small to contain
+ the path, the return value is the size, in TCHARs, of the buffer
+ that is required to hold the path _and_the_terminating_null_character_`
+  */
+  len = GetFullPathName(filename, 0, NULL, NULL);
+
+  if ( len == 0 )
+return strdup(filename);
+
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFullPathName(filename, len, buf, NULL);
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+? (WIN32_UNC_PREFIX_LEN - 2)
+: WIN32_IS_NON_UNC_PREFIX(buf)
+  ? WIN32_NON_UNC_PREFIX_LEN
+  : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+ptr[0] = '/';
+ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# if _WIN32_WINNT >= 0x0600
+
+/* Get full path name WITH symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_final_path_name(HANDLE fh) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+ from the  man: `If the function fails because lpszFilePath is too
+ small to hold the string plus the terminating null character,
+ the return value is the required buffer size, in TCHARs. This
+ value _includes_the_size_of_the_terminating_null_character_`.
+ but in my testcase I have path with 26 chars, the function
+ returns 26 also, ie without the trailing zero-char...
+  */
+  len = GetFinalPathNameByHandle(
+ fh
+,NULL
+,0
+,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+
+  if ( len == 0 )
+return NULL;
+
+  len += 1; /* for zero-char */
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFinalPathNameByHandle(
+ fh
+,buf
+,len
+,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+? (WIN32_UNC_PREFIX_LEN - 2)
+: WIN32_IS_NON_UNC_PREFIX(buf)
+  ? WIN32_NON_UNC_PREFIX_LEN
+  : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+ptr[0] = '/';
+ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# endif // _WIN32_WINNT >= 0x0600
+
+# endif // _WIN32
 #endif
 
 char *
@@ -128,30 +255,52 @@ lrealpath (const char *filename)
   }
 #endif
 
-  /* The MS Windows method.  If we don't have realpath, we assume we
- don't have symlinks and just canonicalize to a Windows absolute
- path.  GetFullPath converts ../ and ./ in relative paths to
- absolute paths, filling in current drive if one is not given
- or using the current directory of a specified drive (eg, "E:foo").
- It also converts all forward slashes to back slashes.  */
+  /* The MS Windows method */
 #if defined (_WIN32)
   {
-char buf[MAX_PATH];
-char* basename;
-DWORD len = GetFullPathName (filename, MAX_PATH, buf, );
-if (len == 0 || len > MAX_PATH - 1)
-  return strdup (filename);
-else
-  {
-	/* The file system is case-preserving but case-insensitive,
-	   Canonicalize to lowercase, using the codepage associated
-	   with the process locale.  */
-CharLowerBuff (buf, len);
-return strdup (buf);
-  }
-  }
-#endif
+char *res;
+

Re: realpath() patch to fix symlinks resolution for win32

2023-01-16 Thread i.nixman--- via Gcc-patches


updated patch in attachments.
diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c
index 3c7053b0b70..8858619e854 100644
--- a/libiberty/lrealpath.c
+++ b/libiberty/lrealpath.c
@@ -68,8 +68,138 @@ extern char *canonicalize_file_name (const char *);
   /* cygwin has realpath, so it won't get here.  */ 
 # if defined (_WIN32)
 #  define WIN32_LEAN_AND_MEAN
-#  include  /* for GetFullPathName */
-# endif
+#  include  /* for GetFullPathName/GetFinalPathNameByHandle/
+  CreateFile/CloseHandle */
+#  define WIN32_REPLACE_SLASHES(_ptr, _len) \
+ for (unsigned i = 0; i != (_len); ++i) \
+   if ((_ptr)[i] == '\\') (_ptr)[i] = '/';
+
+#  define WIN32_UNC_PREFIX "//?/UNC/"
+#  define WIN32_UNC_PREFIX_LEN (sizeof(WIN32_UNC_PREFIX)-1)
+#  define WIN32_IS_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_UNC_PREFIX, WIN32_UNC_PREFIX_LEN))
+
+#  define WIN32_NON_UNC_PREFIX "//?/"
+#  define WIN32_NON_UNC_PREFIX_LEN (sizeof(WIN32_NON_UNC_PREFIX)-1)
+#  define WIN32_IS_NON_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_NON_UNC_PREFIX, WIN32_NON_UNC_PREFIX_LEN))
+
+# define WIN32_IS_SPECIAL_NUL_FILE(ptr) \
+  (0 == strcasecmp(ptr, "NUL"))
+
+/* Get full path name without symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_full_path_name(const char *filename) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+ from the man: `If the lpBuffer buffer is too small to contain
+ the path, the return value is the size, in TCHARs, of the buffer
+ that is required to hold the path _and_the_terminating_null_character_`
+  */
+  len = GetFullPathName(filename, 0, NULL, NULL);
+
+  if ( len == 0 )
+return strdup(filename);
+
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFullPathName(filename, len, buf, NULL);
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+? (WIN32_UNC_PREFIX_LEN - 2)
+: WIN32_IS_NON_UNC_PREFIX(buf)
+  ? WIN32_NON_UNC_PREFIX_LEN
+  : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+ptr[0] = '/';
+ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# if _WIN32_WINNT >= 0x0600
+
+/* Get full path name WITH symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_final_path_name(HANDLE fh) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+ from the  man: `If the function fails because lpszFilePath is too
+ small to hold the string plus the terminating null character,
+ the return value is the required buffer size, in TCHARs. This
+ value _includes_the_size_of_the_terminating_null_character_`.
+ but in my testcase I have path with 26 chars, the function
+ returns 26 also, ie without the trailing zero-char...
+  */
+  len = GetFinalPathNameByHandle(
+ fh
+,NULL
+,0
+,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+
+  if ( len == 0 )
+return NULL;
+
+  len += 1; /* for zero-char */
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFinalPathNameByHandle(
+ fh
+,buf
+,len
+,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+? (WIN32_UNC_PREFIX_LEN - 2)
+: WIN32_IS_NON_UNC_PREFIX(buf)
+  ? WIN32_NON_UNC_PREFIX_LEN
+  : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+ptr[0] = '/';
+ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# endif // _WIN32_WINNT >= 0x0600
+
+# endif // _WIN32
 #endif
 
 char *
@@ -128,30 +258,51 @@ lrealpath (const char *filename)
   }
 #endif
 
-  /* The MS Windows method.  If we don't have realpath, we assume we
- don't have symlinks and just canonicalize to a Windows absolute
- path.  GetFullPath converts ../ and ./ in relative paths to
- absolute paths, filling in current drive if one is not given
- or using the current directory of a specified drive (eg, "E:foo").
- It also converts all forward slashes to back slashes.  */
+  /* The MS Windows method */
 #if defined (_WIN32)
   {
-char buf[MAX_PATH];
-char* basename;
-DWORD len = GetFullPathName (filename, MAX_PATH, buf, );
-if (len == 0 || len > MAX_PATH - 1)
-  return strdup (filename);
-else
-  {
-	/* The file system is case-preserving but case-insensitive,
-	   Canonicalize to lowercase, using the codepage associated
-	   with the process locale.  */
-CharLowerBuff (buf, len);
-return strdup (buf);
+char *res;
+/* For Windows Vista and greater */
+#if _WIN32_WINNT >= 0x0600
+
+/* For some reason the function receives 

lrealpath() patch to fix symlinks resolution for win32

2023-01-16 Thread i.nixman--- via Gcc-patches


hello,

I just finished with https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108350

could anyone review and apply the attached patch please?


GCC master was succesfully bootstrapped as x86_64-w64-mingw32.



best!
diff --git a/libiberty/lrealpath.c b/libiberty/lrealpath.c
index 3c7053b0b70..8858619e854 100644
--- a/libiberty/lrealpath.c
+++ b/libiberty/lrealpath.c
@@ -68,8 +68,138 @@ extern char *canonicalize_file_name (const char *);
   /* cygwin has realpath, so it won't get here.  */ 
 # if defined (_WIN32)
 #  define WIN32_LEAN_AND_MEAN
-#  include  /* for GetFullPathName */
-# endif
+#  include  /* for GetFullPathName/GetFinalPathNameByHandle/
+  CreateFile/CloseHandle */
+#  define WIN32_REPLACE_SLASHES(_ptr, _len) \
+ for (unsigned i = 0; i != (_len); ++i) \
+   if ((_ptr)[i] == '\\') (_ptr)[i] = '/';
+
+#  define WIN32_UNC_PREFIX "//?/UNC/"
+#  define WIN32_UNC_PREFIX_LEN (sizeof(WIN32_UNC_PREFIX)-1)
+#  define WIN32_IS_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_UNC_PREFIX, WIN32_UNC_PREFIX_LEN))
+
+#  define WIN32_NON_UNC_PREFIX "//?/"
+#  define WIN32_NON_UNC_PREFIX_LEN (sizeof(WIN32_NON_UNC_PREFIX)-1)
+#  define WIN32_IS_NON_UNC_PREFIX(ptr) \
+  (0 == memcmp(ptr, WIN32_NON_UNC_PREFIX, WIN32_NON_UNC_PREFIX_LEN))
+
+# define WIN32_IS_SPECIAL_NUL_FILE(ptr) \
+  (0 == memcmp(ptr, "NUL", 3) || 0 == memcmp(ptr, "nul", 3))
+
+/* Get full path name without symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_full_path_name(const char *filename) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+ from the man: `If the lpBuffer buffer is too small to contain
+ the path, the return value is the size, in TCHARs, of the buffer
+ that is required to hold the path _and_the_terminating_null_character_`
+  */
+  len = GetFullPathName(filename, 0, NULL, NULL);
+
+  if ( len == 0 )
+return strdup(filename);
+
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFullPathName(filename, len, buf, NULL);
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+? (WIN32_UNC_PREFIX_LEN - 2)
+: WIN32_IS_NON_UNC_PREFIX(buf)
+  ? WIN32_NON_UNC_PREFIX_LEN
+  : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+ptr[0] = '/';
+ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# if _WIN32_WINNT >= 0x0600
+
+/* Get full path name WITH symlinks resolution.
+   It also converts all forward slashes to back slashes.
+*/
+char* get_final_path_name(HANDLE fh) {
+  DWORD len;
+  char *buf, *ptr, *res;
+
+  /* determining the required buffer size.
+ from the  man: `If the function fails because lpszFilePath is too
+ small to hold the string plus the terminating null character,
+ the return value is the required buffer size, in TCHARs. This
+ value _includes_the_size_of_the_terminating_null_character_`.
+ but in my testcase I have path with 26 chars, the function
+ returns 26 also, ie without the trailing zero-char...
+  */
+  len = GetFinalPathNameByHandle(
+ fh
+,NULL
+,0
+,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+
+  if ( len == 0 )
+return NULL;
+
+  len += 1; /* for zero-char */
+  buf = (char *)malloc(len);
+
+  /* no point to check the result again */
+  len = GetFinalPathNameByHandle(
+ fh
+,buf
+,len
+,FILE_NAME_NORMALIZED | VOLUME_NAME_DOS
+  );
+  buf[len] = 0;
+
+  /* replace slashes */
+  WIN32_REPLACE_SLASHES(buf, len);
+
+  /* calculate offset based on prefix type */
+  len = WIN32_IS_UNC_PREFIX(buf)
+? (WIN32_UNC_PREFIX_LEN - 2)
+: WIN32_IS_NON_UNC_PREFIX(buf)
+  ? WIN32_NON_UNC_PREFIX_LEN
+  : 0
+  ;
+
+  ptr = buf + len;
+  if ( WIN32_IS_UNC_PREFIX(buf) ) {
+ptr[0] = '/';
+ptr[1] = '/';
+  }
+
+  res = strdup(ptr);
+
+  free(buf);
+
+  return res;
+}
+
+# endif // _WIN32_WINNT >= 0x0600
+
+# endif // _WIN32
 #endif
 
 char *
@@ -128,30 +258,51 @@ lrealpath (const char *filename)
   }
 #endif
 
-  /* The MS Windows method.  If we don't have realpath, we assume we
- don't have symlinks and just canonicalize to a Windows absolute
- path.  GetFullPath converts ../ and ./ in relative paths to
- absolute paths, filling in current drive if one is not given
- or using the current directory of a specified drive (eg, "E:foo").
- It also converts all forward slashes to back slashes.  */
+  /* The MS Windows method */
 #if defined (_WIN32)
   {
-char buf[MAX_PATH];
-char* basename;
-DWORD len = GetFullPathName (filename, MAX_PATH, buf, );
-if (len == 0 || len > MAX_PATH - 1)
-  return strdup (filename);
-else
-  {
-	/* The file system is case-preserving but case-insensitive,
-	   Canonicalize to lowercase, using the codepage associated
-	   with the process 

Re: Adding a new thread model to GCC

2022-12-24 Thread i.nixman--- via Gcc-patches

On 2022-12-24 15:57, i.nix...@autistici.org wrote:

On 2022-12-24 15:42, i.nix...@autistici.org wrote:


fixed and tested.

Jonathan Yong, could you please apply the attached patch too?



kings regards!


oh no...

please wait.


fixed now.
bootstrapped successfully!


Jonathan Yong, could you please apply the attached patch too?



best!
diff --git a/libgcc/config/i386/gthr-win32.h b/libgcc/config/i386/gthr-win32.h
index 9485dd50bf9..146357fa436 100644
--- a/libgcc/config/i386/gthr-win32.h
+++ b/libgcc/config/i386/gthr-win32.h
@@ -93,8 +93,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #endif
 #define WIN32_LEAN_AND_MEAN
 #include 
-/* Now undef the windows BOOL.  */
+/* Now undef the windows BOOL and CC_NONE */
 #undef BOOL
+#undef CC_NONE
 
 /* Key structure for maintaining thread specific storage */
 static DWORD __gthread_objc_data_tls = TLS_OUT_OF_INDEXES;
@@ -604,6 +605,7 @@ __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
 
 #define WIN32_LEAN_AND_MEAN
 #include 
+#undef CC_NONE
 
 __GTHREAD_WIN32_INLINE int
 __gthread_detach (__gthread_t __thr)


Re: Adding a new thread model to GCC

2022-12-24 Thread i.nixman--- via Gcc-patches

On 2022-12-24 15:42, i.nix...@autistici.org wrote:


fixed and tested.

Jonathan Yong, could you please apply the attached patch too?



kings regards!


oh no...

please wait.


Re: Adding a new thread model to GCC

2022-12-24 Thread i.nixman--- via Gcc-patches

On 2022-12-24 13:50, i.nix...@autistici.org wrote:

On 2022-12-24 05:58, NightStrike wrote:


I think this might have broken fortran.  I'm assuming because the
backtrace includes gthr.h, and I just did a git pull:

In file included from /tmp/rtmingw/mingw/include/windows.h:71,
 from ../libgcc/gthr-default.h:606,
 from ../../../libgfortran/../libgcc/gthr.h:148,
 from ../../../libgfortran/io/io.h:33,
 from ../../../libgfortran/runtime/error.c:27:
../../../libgfortran/io/io.h:298:24: error: expected identifier before
numeric constant
  298 | { CC_LIST, CC_FORTRAN, CC_NONE,
  |^~~



yes, you are right!
this is because the `CC_NONE` was previously defined in `wingdi.h` as
`#define CC_NONE 0`

thinking...


fixed and tested.

Jonathan Yong, could you please apply the attached patch too?



kings regards!
diff --git a/libgcc/config/i386/gthr-win32.h b/libgcc/config/i386/gthr-win32.h
index 9485dd50bf9..2b5b782c894 100644
--- a/libgcc/config/i386/gthr-win32.h
+++ b/libgcc/config/i386/gthr-win32.h
@@ -93,8 +93,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #endif
 #define WIN32_LEAN_AND_MEAN
 #include 
-/* Now undef the windows BOOL.  */
+/* Now undef the windows BOOL and CC_NONE */
 #undef BOOL
+#undef CC_NONE
 
 /* Key structure for maintaining thread specific storage */
 static DWORD __gthread_objc_data_tls = TLS_OUT_OF_INDEXES;


Re: Adding a new thread model to GCC

2022-12-24 Thread i.nixman--- via Gcc-patches

On 2022-12-24 05:58, NightStrike wrote:


I think this might have broken fortran.  I'm assuming because the
backtrace includes gthr.h, and I just did a git pull:

In file included from /tmp/rtmingw/mingw/include/windows.h:71,
 from ../libgcc/gthr-default.h:606,
 from ../../../libgfortran/../libgcc/gthr.h:148,
 from ../../../libgfortran/io/io.h:33,
 from ../../../libgfortran/runtime/error.c:27:
../../../libgfortran/io/io.h:298:24: error: expected identifier before
numeric constant
  298 | { CC_LIST, CC_FORTRAN, CC_NONE,
  |^~~



yes, you are right!
this is because the `CC_NONE` was previously defined in `wingdi.h` as 
`#define CC_NONE 0`


thinking...


Re: Adding a new thread model to GCC

2022-12-23 Thread i.nixman--- via Gcc-patches

On 2022-12-24 05:58, NightStrike wrote:


I think this might have broken fortran.  I'm assuming because the
backtrace includes gthr.h, and I just did a git pull:

In file included from /tmp/rtmingw/mingw/include/windows.h:71,
 from ../libgcc/gthr-default.h:606,
 from ../../../libgfortran/../libgcc/gthr.h:148,
 from ../../../libgfortran/io/io.h:33,
 from ../../../libgfortran/runtime/error.c:27:
../../../libgfortran/io/io.h:298:24: error: expected identifier before
numeric constant
  298 | { CC_LIST, CC_FORTRAN, CC_NONE,
  |^~~



hmm...

I don't remember if I specified `fortran` in `--enable-language` in my 
test builds...

will try to build again now...


Re: Adding a new thread model to GCC

2022-12-23 Thread i.nixman--- via Gcc-patches

On 2022-12-23 23:59, Jonathan Yong wrote:


Done, pushed to master branch. Thanks Eric.



thank you Jonathan!


Re: Adding a new thread model to GCC

2022-12-22 Thread i.nixman--- via Gcc-patches

On 2022-12-22 12:21, Jonathan Yong wrote:

hello,


On 12/16/22 19:20, Eric Botcazou wrote:

The libgcc parts look reasonable to me, but I can't approve them.
Maybe Jonathan Yong can approve those parts as mingw-w64 target
maintainer, or maybe a libgcc approver can do so.


OK.


The libstdc++ parts are OK for trunk. IIUC they could go in
separately, they just wouldn't be very much use without the libgcc
changes.


Sure thing.



Ping, need help to commit it?


yes, it would be great if we can merge the path into gcc-13!

I've tested it on gcc-12-branch and gcc-master for i686/x86_64 windows, 
with msvcrt and ucrt runtime - works as it should!


Eric ^^^



best!


Re: Adding a new thread model to GCC

2022-11-02 Thread i.nixman--- via Gcc-patches

On 2022-11-02 21:27, Eric Botcazou wrote:

Great!  Did you check that C++ threads are enabled in your build?  If 
they
are, you must be able to run the attached C++ test; if they are not 
(because
the MinGW64 build is configured for older versions of Windows), you 
need to

configure the compiler with the option --enable-libstdcxx-threads.


I already checked everything before, but now I re-checked it again - 
everything works!


the output:
$ ./t
Start thread 0
Start thread 1
Start thread 2
Start thread 3


thank you!


Re: Adding a new thread model to GCC

2022-11-02 Thread i.nixman--- via Gcc-patches



hi Eric, Jonathan,

I was able to successfully build gcc-trunk using the provided patch.
moreover, I was able to successfully build all of the packages used in 
the toolchain!
(gmp, mpfr, mpc, isl, libgnurx, bzip2, termcap, libffi, expat, ncurses, 
readline, gdbm, tcl, tk, openssl, xz-utils, sqlite, python3, binutils, 
gdb, make)


at first glance everything seems to be working as before!
I posted the information about this and the link to the archive on the 
project page: https://github.com/niXman/mingw-builds/issues/622




best!


Re: Adding a new thread model to GCC

2022-10-31 Thread i.nixman--- via Gcc-patches

On 2022-10-31 09:18, Eric Botcazou wrote:

hello Eric!

This also changes libstdc++ to pass -D_WIN32_WINNT=0x0600 but only when 
the
switch --enable-libstdcxx-threads is passed, which means that C++11 
threads
are still disabled by default *unless* MinGW-W64 itself is configured 
for
Windows Vista/Server 2008 or later by default (this has been the case 
in

the development version since end of 2020, for earlier versions you can
configure it --with-default-win32-winnt=0x0600 to get the same effect).


I have faced with "#error Timed lock primitives are not supported on 
Windows targets" and I'm not sure I understood the reason correctly.


as far as I understand, the definition for 
`_GTHREAD_USE_MUTEX_TIMEDLOCK` comes from libstdc++/configure as a 
result of some test.


why did I faced with this error? what should I do to avoid this?



you can configure it --with-default-win32-winnt=0x0600 to get the same 
effect


are you talking about the `--with-default-win32-winnt=` option used on 
MinGW-builds script?





best!


Re: Adding a new thread model to GCC

2022-10-31 Thread i.nixman--- via Gcc-patches

On 2022-10-31 09:18, Eric Botcazou wrote:

Hi Eric!

thank you very much for the job!
I will try to build our (MinGW-Builds project) builds using this patch 
and will report back.


@Jonathan

what the next steps to be taken to accept this patch?



best!



I have attached a revised version of the original patch at:
  https://gcc.gnu.org/legacy-ml/gcc-patches/2019-06/msg01840.html

This reimplements the GNU threads library on native Windows (except for 
the
Objective-C specific subset) using direct Win32 API calls, in lieu of 
the

implementation based on semaphores.  This base implementations requires
Windows XP/Server 2003, which was the default minimal setting of 
MinGW-W64
until end of 2020.  This also adds the support required for the C++11 
threads,
using again direct Win32 API calls; this additional layer requires 
Windows

Vista/Server 2008 and is enabled only if _WIN32_WINNT >= 0x0600.

This also changes libstdc++ to pass -D_WIN32_WINNT=0x0600 but only when 
the
switch --enable-libstdcxx-threads is passed, which means that C++11 
threads
are still disabled by default *unless* MinGW-W64 itself is configured 
for
Windows Vista/Server 2008 or later by default (this has been the case 
in

the development version since end of 2020, for earlier versions you can
configure it --with-default-win32-winnt=0x0600 to get the same effect).

I only manually tested it on i686-w64-mingw32 and x86_64-w64-mingw32 
but
AdaCore has used it in their C/C++/Ada compilers for 3 years now and 
the

30_threads chapter of the libstdc++ testsuite was clean at the time.


2022-10-31  Eric Botcazou  

libgcc/
* config.host (i[34567]86-*-mingw*): Add thread fragment after EH one
as well as new i386/t-slibgcc-mingw fragment.
(x86_64-*-mingw*): Likewise.
* config/i386/gthr-win32.h: If _WIN32_WINNT is at least 0x0600, define
both __GTHREAD_HAS_COND and __GTHREADS_CXX0X to 1.
Error out if _GTHREAD_USE_MUTEX_TIMEDLOCK is 1.
Include stdlib.h instead of errno.h and do not include _mingw.h.
(CONST_CAST2): Add specific definition for C++.
(ATTRIBUTE_UNUSED): New macro.
(__UNUSED_PARAM): Delete.
Define WIN32_LEAN_AND_MEAN before including windows.h.
	(__gthread_objc_data_tls): Use TLS_OUT_OF_INDEXES instead of 
(DWORD)-1.

(__gthread_objc_init_thread_system): Likewise.
(__gthread_objc_thread_get_data): Minor tweak.
(__gthread_objc_condition_allocate): Use ATTRIBUTE_UNUSED.
(__gthread_objc_condition_deallocate): Likewise.
(__gthread_objc_condition_wait): Likewise.
(__gthread_objc_condition_broadcast): Likewise.
(__gthread_objc_condition_signal): Likewise.
Include sys/time.h.
(__gthr_win32_DWORD): New typedef.
(__gthr_win32_HANDLE): Likewise.
(__gthr_win32_CRITICAL_SECTION): Likewise.
(__gthr_win32_CONDITION_VARIABLE): Likewise.
(__gthread_t): Adjust.
(__gthread_key_t): Likewise.
(__gthread_mutex_t): Likewise.
(__gthread_recursive_mutex_t): Likewise.
(__gthread_cond_t): New typedef.
(__gthread_time_t): Likewise.
(__GTHREAD_MUTEX_INIT_DEFAULT): Delete.
(__GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT): Likewise.
(__GTHREAD_COND_INIT_FUNCTION): Define.
(__GTHREAD_TIME_INIT): Likewise.
(__gthr_i486_lock_cmp_xchg): Delete.
(__gthr_win32_create): Declare.
(__gthr_win32_join): Likewise.
(__gthr_win32_self): Likewise.
(__gthr_win32_detach): Likewise.
(__gthr_win32_equal): Likewise.
(__gthr_win32_yield): Likewise.
(__gthr_win32_mutex_destroy): Likewise.
	(__gthr_win32_cond_init_function): Likewise if __GTHREADS_HAS_COND is 
1.

(__gthr_win32_cond_broadcast): Likewise.
(__gthr_win32_cond_signal): Likewise.
(__gthr_win32_cond_wait): Likewise.
(__gthr_win32_cond_timedwait): Likewise.
(__gthr_win32_recursive_mutex_init_function): Delete.
(__gthr_win32_recursive_mutex_lock): Likewise.
(__gthr_win32_recursive_mutex_unlock): Likewise.
(__gthr_win32_recursive_mutex_destroy): Likewise.
(__gthread_create): New inline function.
(__gthread_join): Likewise.
(__gthread_self): Likewise.
(__gthread_detach): Likewise.
(__gthread_equal): Likewise.
(__gthread_yield): Likewise.
(__gthread_cond_init_function): Likewise if __GTHREADS_HAS_COND is 1.
(__gthread_cond_broadcast): Likewise.
(__gthread_cond_signal): Likewise.
(__gthread_cond_wait): Likewise.
(__gthread_cond_timedwait): Likewise.
(__GTHREAD_WIN32_INLINE): New macro.
(__GTHREAD_WIN32_COND_INLINE): Likewise.
(__GTHREAD_WIN32_ACTIVE_P): Likewise.
Define WIN32_LEAN_AND_MEAN before including windows.h.
(__gthread_once): Minor tweaks.
(__gthread_key_create): Use ATTRIBUTE_UNUSED and TLS_OUT_OF_INDEXES.
  

Re: Adding a new thread model to GCC

2022-10-24 Thread i.nixman--- via Gcc-patches

On 2022-10-24 08:15, Eric Botcazou wrote:

could you please refresh/recheck your patch for the current gcc master
and solve the objections noted in the thread? is it possible?





Hi,


I can do the former, but not the latter as my development setup (mostly
testing) on Windows has nearly vanished in the meantime.  But this 
rewritten

implementation is the one used by the C/C++/Ada compilers from AdaCore.



ah, it's great!


thank you very much!




best!


Re: Adding a new thread model to GCC

2022-10-24 Thread i.nixman--- via Gcc-patches

On 2022-10-21 11:44, Eric Botcazou via Libstdc++ wrote:

How does this compare with Eric B's proposal at
https://gcc.gnu.org/legacy-ml/gcc-patches/2019-06/msg01840.html ?


My proposal was to reimplement (and extend) the native thread model 
(win32)
instead of adding a new one, the advantage being that you don't need an 
extra

threading layer between GCC and Windows.


Hello Eric,

could you please refresh/recheck your patch for the current gcc master 
and solve the objections noted in the thread? is it possible?




best!


Re: Adding a new thread model to GCC

2022-10-21 Thread i.nixman--- via Gcc-patches

On 2022-10-21 12:19, LIU Hao wrote:

在 2022/10/21 19:54, i.nix...@autistici.org 写道:





Jacek Caban, who is also a mingw-w64 developer, expressed the same
idea a few days ago.

While integrating mcfgthread into gcc is practically possible, my 
concerns are:


  * GCC never provides a threading library. It always depends on glibc,
musl, win32 APIs, winpthreads, etc.


I think you didn't understand me.

I mean not to integrate your library into GCC as real separate library.
I mean to do changes on 
config/i386/gthr-win32.h+config/i386/gthr-win32.c+config/i386/gthr-win32-cond.c 
etc using your code to have an implementation of everything needed for 
C/C++ threads on Windows.




  * Tampering with the win32 thread model in a dramatic way is not
acceptiable due to backwards compatibility. There are distributions
that have win32 as the default thread model, such as Debian.

  * I personally need more control for future development, for example,
re-implement pthread or adding libcxx support, which doesn't fit in
GCC.


got it...
anyway it seems logical to me the way I proposed :)


best!


Re: Adding a new thread model to GCC

2022-10-21 Thread i.nixman--- via Gcc-patches

On 2022-10-21 11:44, Eric Botcazou via Libstdc++ wrote:

How does this compare with Eric B's proposal at
https://gcc.gnu.org/legacy-ml/gcc-patches/2019-06/msg01840.html ?


My proposal was to reimplement (and extend) the native thread model 
(win32)
instead of adding a new one, the advantage being that you don't need an 
extra

threading layer between GCC and Windows.


I agree!



best!


Re: Adding a new thread model to GCC

2022-10-21 Thread i.nixman--- via Gcc-patches

On 2022-10-21 11:36, LIU Hao wrote:

在 2022/10/21 18:09, i.nix...@autistici.org 写道:

On 2022-10-21 09:58, Jonathan Wakely via Libstdc++ wrote:

How does this compare with Eric B's proposal at
https://gcc.gnu.org/legacy-ml/gcc-patches/2019-06/msg01840.html ?

It would be good if we can accept one of them for GCC 13, but I don't
know Windows well enough to determine which is better.


I had the same question...
I would like to understand what is the difference?
Moreover I would like to understand what is the difference with the 
already added support for the winpthreads library?


@LIU Hao, could you explain please?





Thank you for your interest. I'm glad to make an introduction of it.


I have read this patch before. Let's take the mutex as an example:

There are a lot of ways to implement a mutex on Windows. Basically, a
non-recursive mutex can be implemented with an atomic counter + a
binary semaphore / auto-reset event. This proposed patch contains a
`__gthr_win32_CRITICAL_SECTION` definition that I think is a duplicate
of the internal `CRITICAL_SECTION` structure, so should also work the
same way as it.

The problem about this approach is that, semaphores are valuable
kernel objects, and the maximum number of HANDLEs that a process can
open concurrently has a limit (like FDs on Linux), while 'many
critical sections are used only occasionally (or never at all),
meaning the auto-reset event often isn’t even necessary' [1], the
semaphores are actually allocated on demand. This means that locking
can fail. There is a story in article [1] which also explains the
origination of keyed events; it's worth reading.

And, since Vista we also have native win32 condition variables, also
implemented basing on keyed events.


The keyed events are undocumented and are only exposed via syscalls.
However, as with other documented syscalls, available from Windows
Drivers Kit, there are several advantages:

  * There is a global keyed event, which requires no initialization, 
but
can be utilized by all processes. Basing on that, mcfgthread 
provides
mutexs, condition variables, once flags, etc. that are all 
one-pointer

size structs, consume absolutely no additional resource, allow
constexpr initialization, and require no cleanup, much like on 
Linux.


  * The wait syscalls take a 64-bit integer, whose positive value 
denotes

the number of 10^-7 seconds since 1600-01-01 00:00:00 Z, and whose
negative value denotes a relative timeout. Hence it's much more 
simpler
to implement `__gthread_mutex_timedlock()` and 
`__gthread_cond_wait()`
which take absolute timeouts. On the other hand, Win32 APIs 
generally
take a 32-bit relative timeout in milliseconds, which not only 
requires
translation from an absolute timepoint argument, but can also 
easily

get overflown.

  * Building mutexes on top of syscalls allows a better designed 
algorithm

[2], and sometimes it can even outperform native `SRWLOCK`s [3].

  * mcfgthread also provides standard-conforming `__cxa_atexit()` and
`__cxa_thread_atexit()` functions, for working around some strange,
weird, and broken behaviors [4][5][6]. On Linux it's glibc that
provides them, so this as a whole requires a little modification in
mingw-w64. I am working on it however; hopefully we can land it 
soon.





thank you LIU Hao for the explanation!

I have a questions:
1) wouldn't it be logical not to write yet another implementation of 
pthreads-wor-windows, but to make changes to the winpthreads library 
because it's already supported by GCC? (maybe I don’t know about some 
reasons why it wasn’t done ...)


It seems to me the ideal and logical option is to make your 
implementation part of GCC, as suggested by Eric B.

the advantages are as follows:
1) we will get a high-quality native implementation.
2) there is no need to add another thread model for GCC.
3) with dynamic linking there is no need to ship another dll with the 
program. (Windows users really don't like this =))




best!

[1] 
http://joeduffyblog.com/2006/11/28/windows-keyed-events-critical-sections-and-new-vista-synchronization-features/


[2] https://github.com/lhmouse/mcfgthread/blob/master/MUTEX.md
[3] https://github.com/lhmouse/mcfgthread#benchmarking

[4] https://sourceforge.net/p/mingw-w64/mailman/message/37268447/
[5] https://reviews.llvm.org/D102944
[6] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80816


Re: Adding a new thread model to GCC

2022-10-21 Thread i.nixman--- via Gcc-patches

On 2022-10-21 10:48, Jonathan Wakely wrote:

On Fri, 21 Oct 2022 at 11:10, i.nixman--- via Libstdc++
 wrote:


On 2022-10-21 09:58, Jonathan Wakely via Libstdc++ wrote:
> How does this compare with Eric B's proposal at
> https://gcc.gnu.org/legacy-ml/gcc-patches/2019-06/msg01840.html ?
>
> It would be good if we can accept one of them for GCC 13, but I don't
> know Windows well enough to determine which is better.

I had the same question...
I would like to understand what is the difference?
Moreover I would like to understand what is the difference with the
already added support for the winpthreads library?


Well that one's easy, you don't need to use winpthreads if there's a
native thread model, so you don't need to go through two abstraction
layers (gthreads and winpthreads), just one (gthreads).



sure!

nevertheless I would like to understand why we have two separate 
implementations (winthreads and mcfgthread)?

what is the difference?


best!


Re: Adding a new thread model to GCC

2022-10-21 Thread i.nixman--- via Gcc-patches

On 2022-10-21 09:58, Jonathan Wakely via Libstdc++ wrote:

How does this compare with Eric B's proposal at
https://gcc.gnu.org/legacy-ml/gcc-patches/2019-06/msg01840.html ?

It would be good if we can accept one of them for GCC 13, but I don't
know Windows well enough to determine which is better.


I had the same question...
I would like to understand what is the difference?
Moreover I would like to understand what is the difference with the 
already added support for the winpthreads library?


@LIU Hao, could you explain please?



best!



On Sat, 1 Oct 2022 at 19:35, LIU Hao via Libstdc++
 wrote:


Greetings.

After some years I think it's time to put on this topic again.

This patch series is an attempt to add a new thread model basing on 
the mcfgthread library
(https://github.com/lhmouse/mcfgthread), which provides efficient 
implementations of mutexes,

condition variables, once flags, etc. for native Windows.


The first patch is necessary because somewhere in libgfortran, 
`pthread_t` is referenced. If the

thread model is not `posix`, it fails to compile.

The second patch implements `std::thread::hardware_concurrency()` for 
non-posix thread models. This
would also work for the win32 thread model if `std::thread` would be 
supported in the future.


The third patch adds the `mcf` thread model for GCC and its libraries. 
A new builtin macro
`__USING_MCFGTHREAD__` is added to indicate whether this new thread 
model is in effect. This grants
`std::mutex` and `std::once_flag` trivial destructors; 
`std::condition_variable` is a bit
unfortunate because its destructor is non-trivial, but in reality no 
cleanup is performed.



I have been bootstrapping GCC with the MCF thread model for more than 
five years. At the moment, C,
C++ and Fortran are supported. Ada is untested because I don't know 
how to bootstrap it. Objective-C
is not supported, because threading APIs for libobjc have not been 
implemented.


Please review. If there are any changes that I have to make, let me 
know.



--
Best regards,
LIU Hao