public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Adding a new thread model to GCC
@ 2022-10-01 18:34 LIU Hao
  2022-10-01 20:02 ` Bernhard Reutner-Fischer
  2022-10-21  9:58 ` Jonathan Wakely
  0 siblings, 2 replies; 58+ messages in thread
From: LIU Hao @ 2022-10-01 18:34 UTC (permalink / raw)
  To: gcc-patches, libstdc++


[-- Attachment #1.1.1: Type: text/plain, Size: 1462 bytes --]

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

[-- Attachment #1.1.2: 0001-libgfortran-Use-__gthread_t-instead-of-pthread_t.patch --]
[-- Type: text/plain, Size: 969 bytes --]

From c522fa74c791ee8904b5906c6e18908b56071db5 Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Fri, 27 May 2022 23:12:48 +0800
Subject: [PATCH 1/3] libgfortran: Use `__gthread_t` instead of `pthread_t`

It used to cause errors if a thread model other than `posix` was selected,
which looks like a leftover from a79878585a1c5e32bafbc6d1e73f91fd6e4293bf.

libgfortran/ChangeLog:
	* io/async.h (struct async_unit): Use `__gthread_t` instead
	of `pthread_t`.
---
 libgfortran/io/async.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libgfortran/io/async.h b/libgfortran/io/async.h
index efd542a45e82..d57722a95e44 100644
--- a/libgfortran/io/async.h
+++ b/libgfortran/io/async.h
@@ -351,7 +351,7 @@ typedef struct async_unit
   struct adv_cond work;
   struct adv_cond emptysignal;
   struct st_parameter_dt *pdt;
-  pthread_t thread;
+  __gthread_t thread;
   struct transfer_queue *head;
   struct transfer_queue *tail;
 
-- 
2.37.3


[-- Attachment #1.1.3: 0002-libstdc-thread-Implement-_GLIBCXX_NPROCS-for-Windows.patch --]
[-- Type: text/plain, Size: 1166 bytes --]

From fcae3b25b859a207152927797c5ebc520ef3d61a Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Sun, 2 Oct 2022 00:57:08 +0800
Subject: [PATCH 2/3] libstdc++/thread: Implement `_GLIBCXX_NPROCS` for Windows

This makes `std::thread::hardware_concurrency()` return the number of
logical processors, instead of zero.

libstdc++-v3/ChangeLog:
	* src/c++11/thread.cc (get_nprocs): Add new implementation
	for native Windows targets
---
 libstdc++-v3/src/c++11/thread.cc | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc
index 707a4ad415b9..b39d9f4a9e29 100644
--- a/libstdc++-v3/src/c++11/thread.cc
+++ b/libstdc++-v3/src/c++11/thread.cc
@@ -68,6 +68,15 @@ static inline int get_nprocs()
 #elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
 # include <unistd.h>
 # define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
+#elif defined(_WIN32)
+# include <windows.h>
+static inline int get_nprocs()
+{
+  SYSTEM_INFO sysinfo;
+  GetSystemInfo(&sysinfo);
+  return (int)sysinfo.dwNumberOfProcessors;
+}
+# define _GLIBCXX_NPROCS get_nprocs()
 #else
 # define _GLIBCXX_NPROCS 0
 #endif
-- 
2.37.3


[-- Attachment #1.1.4: 0003-gcc-Add-mcf-thread-model-support-from-mcfgthread.patch --]
[-- Type: text/plain, Size: 9383 bytes --]

From d0f78f3f83d134d91b59e553b115521f8d67ef52 Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Sat, 16 Apr 2022 00:46:23 +0800
Subject: [PATCH 3/3] gcc: Add 'mcf' thread model support from mcfgthread

This patch adds the new thread model `mcf`, which implements mutexes
and condition variables with the mcfgthread library.

Source code for mcfgthread is available at <https://github.com/lhmouse/mcfgthread>.

config/ChangeLog:
	* gthr.m4 (GCC_AC_THREAD_HEADER): Add new case for `mcf` thread
	model

gcc/config/ChangeLog:
	* i386/mingw-mcfgthread.h: New file
	* i386/mingw32.h: Add builtin macro and default libraries for
	mcfgthread when thread model is `mcf`

gcc/ChangeLog:
	* config.gcc: Include 'i386/mingw-mcfgthread.h' when thread model
	is `mcf`
	* configure.ac: Recognize `mcf` as a valid thread model

libatomic/ChangeLog:
	* configure.tgt: Add new case for `mcf` thread model

libgcc/ChangeLog:
	* config.host: Add new cases for `mcf` thread model
	* config/i386/gthr-mcf.h: New file
	* config/i386/t-mingw-mcfgthread: New file
	* config/i386/t-slibgcc-cygming: Make CRT depend on threading
	library, not vice versa

libstdc++-v3/ChangeLog:
	* libsupc++/atexit_thread.cc (__cxa_thread_atexit): Use
	implementation from mcfgthread if available
	* libsupc++/guard.cc (__cxa_guard_acquire, __cxa_guard_release,
	__cxa_guard_abort): Use implementations from mcfgthread if
	available
---
 config/gthr.m4                          |  1 +
 gcc/config.gcc                          |  3 +++
 gcc/config/i386/mingw-mcfgthread.h      |  1 +
 gcc/config/i386/mingw32.h               | 11 ++++++++-
 gcc/configure.ac                        |  2 +-
 libatomic/configure.tgt                 |  2 +-
 libgcc/config.host                      |  6 +++++
 libgcc/config/i386/gthr-mcf.h           |  1 +
 libgcc/config/i386/t-mingw-mcfgthread   |  2 ++
 libgcc/config/i386/t-slibgcc-cygming    |  2 +-
 libstdc++-v3/libsupc++/atexit_thread.cc | 20 ++++++++++++++++
 libstdc++-v3/libsupc++/guard.cc         | 31 +++++++++++++++++++++++++
 12 files changed, 78 insertions(+), 4 deletions(-)
 create mode 100644 gcc/config/i386/mingw-mcfgthread.h
 create mode 100644 libgcc/config/i386/gthr-mcf.h
 create mode 100644 libgcc/config/i386/t-mingw-mcfgthread

diff --git a/config/gthr.m4 b/config/gthr.m4
index 4b937306ad08..11996247f150 100644
--- a/config/gthr.m4
+++ b/config/gthr.m4
@@ -22,6 +22,7 @@ case $1 in
     tpf)	thread_header=config/s390/gthr-tpf.h ;;
     vxworks)	thread_header=config/gthr-vxworks.h ;;
     win32)	thread_header=config/i386/gthr-win32.h ;;
+    mcf)	thread_header=config/i386/gthr-mcf.h ;;
 esac
 AC_SUBST(thread_header)
 ])
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 555f257c2e7a..4cb31bd41561 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2088,6 +2088,9 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	if test x$enable_threads = xposix ; then
 		tm_file="${tm_file} i386/mingw-pthread.h"
 	fi
+	if test x$enable_threads = xmcf ; then
+		tm_file="${tm_file} i386/mingw-mcfgthread.h"
+	fi
 	tm_file="${tm_file} i386/mingw32.h"
 	# This makes the logic if mingw's or the w64 feature set has to be used
 	case ${target} in
diff --git a/gcc/config/i386/mingw-mcfgthread.h b/gcc/config/i386/mingw-mcfgthread.h
new file mode 100644
index 000000000000..ec381a7798f1
--- /dev/null
+++ b/gcc/config/i386/mingw-mcfgthread.h
@@ -0,0 +1 @@
+#define TARGET_USE_MCFGTHREAD 1
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index d3ca0cd0279d..307a803b92c2 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -32,6 +32,14 @@ along with GCC; see the file COPYING3.  If not see
 	 | MASK_STACK_PROBE | MASK_ALIGN_DOUBLE \
 	 | MASK_MS_BITFIELD_LAYOUT)
 
+#ifndef TARGET_USE_MCFGTHREAD
+#define CPP_MCFGTHREAD()  ((void)0)
+#define LIB_MCFGTHREAD     ""
+#else
+#define CPP_MCFGTHREAD()  (builtin_define("__USING_MCFGTHREAD__"))
+#define LIB_MCFGTHREAD     " -lmcfgthread "
+#endif
+
 /* See i386/crtdll.h for an alternative definition. _INTEGRAL_MAX_BITS
    is for compatibility with native compiler.  */
 #define EXTRA_OS_CPP_BUILTINS()					\
@@ -50,6 +58,7 @@ along with GCC; see the file COPYING3.  If not see
 	  builtin_define_std ("WIN64");				\
 	  builtin_define ("_WIN64");				\
 	}							\
+	CPP_MCFGTHREAD();	\
     }								\
   while (0)
 
@@ -185,7 +194,7 @@ along with GCC; see the file COPYING3.  If not see
 #define REAL_LIBGCC_SPEC \
   "%{mthreads:-lmingwthrd} -lmingw32 \
    " SHARED_LIBGCC_SPEC " \
-   -lmoldname -lmingwex -lmsvcrt -lkernel32"
+   -lmoldname -lmingwex -lmsvcrt " LIB_MCFGTHREAD " -lkernel32 -lntdll"
 
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
diff --git a/gcc/configure.ac b/gcc/configure.ac
index b6bafa8b7d69..0641b8a61dae 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1991,7 +1991,7 @@ case ${enable_threads} in
     target_thread_file='single'
     ;;
   aix | dce | lynx | mipssde | posix | rtems | \
-  single | tpf | vxworks | win32)
+  single | tpf | vxworks | win32 | mcf)
     target_thread_file=${enable_threads}
     ;;
   *)
diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
index 33f8c91ce771..86a59475b6e7 100644
--- a/libatomic/configure.tgt
+++ b/libatomic/configure.tgt
@@ -159,7 +159,7 @@ case "${target}" in
   *-*-mingw*)
 	# OS support for atomic primitives.
         case ${target_thread_file} in
-          win32)
+          win32 | mcf)
             config_path="${config_path} mingw"
             ;;
           posix)
diff --git a/libgcc/config.host b/libgcc/config.host
index 9dcc2538dc86..44a8218a31d3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -825,6 +825,9 @@ i[34567]86-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
@@ -849,6 +852,9 @@ x86_64-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
diff --git a/libgcc/config/i386/gthr-mcf.h b/libgcc/config/i386/gthr-mcf.h
new file mode 100644
index 000000000000..58131bb7ca92
--- /dev/null
+++ b/libgcc/config/i386/gthr-mcf.h
@@ -0,0 +1 @@
+#include <mcfgthread/gthr.h>
diff --git a/libgcc/config/i386/t-mingw-mcfgthread b/libgcc/config/i386/t-mingw-mcfgthread
new file mode 100644
index 000000000000..4b9b10e32d61
--- /dev/null
+++ b/libgcc/config/i386/t-mingw-mcfgthread
@@ -0,0 +1,2 @@
+SHLIB_PTHREAD_CFLAG =
+SHLIB_PTHREAD_LDFLAG = -lmcfgthread
diff --git a/libgcc/config/i386/t-slibgcc-cygming b/libgcc/config/i386/t-slibgcc-cygming
index 6236c78e4668..3ab1312053d7 100644
--- a/libgcc/config/i386/t-slibgcc-cygming
+++ b/libgcc/config/i386/t-slibgcc-cygming
@@ -37,7 +37,7 @@ SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
 	$(SHLIB_MAP).def \
 	-Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \
 	-o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
-	$(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) && \
+	$(SHLIB_OBJS) $(SHLIB_LC) ${SHLIB_PTHREAD_LDFLAG} && \
 	if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
 	  mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
 		$(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
diff --git a/libstdc++-v3/libsupc++/atexit_thread.cc b/libstdc++-v3/libsupc++/atexit_thread.cc
index a2693d0424e1..2f936ab02ce2 100644
--- a/libstdc++-v3/libsupc++/atexit_thread.cc
+++ b/libstdc++-v3/libsupc++/atexit_thread.cc
@@ -25,6 +25,24 @@
 #include <cstdlib>
 #include <new>
 #include "bits/gthr.h"
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
+		     void *obj, void *dso_handle) _GLIBCXX_NOTHROW
+{
+  return __MCF_cxa_thread_atexit (dtor, obj, dso_handle);
+}
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
@@ -173,3 +191,5 @@ __cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
 }
 
 #endif /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */
+
+#endif // __USING_MCFGTHREAD__
diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc
index abb57117cdfd..0f81a22c6845 100644
--- a/libstdc++-v3/libsupc++/guard.cc
+++ b/libstdc++-v3/libsupc++/guard.cc
@@ -28,6 +28,35 @@
 #include <cxxabi.h>
 #include <exception>
 #include <new>
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_guard_acquire (__guard* g) _GLIBCXX_NOTHROW
+  {
+    return __MCF_cxa_guard_acquire(g);
+  }
+
+extern "C" void
+__cxa_guard_release (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_release(g);
+  }
+
+extern "C" void
+__cxa_guard_abort (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_abort(g);
+  }
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #include <ext/atomicity.h>
 #include <ext/concurrence.h>
 #include <bits/atomic_lockfree_defines.h>
@@ -458,3 +487,5 @@ namespace __cxxabiv1
 #endif
   }
 }
+
+#endif // __USING_MCFGTHREAD__
-- 
2.37.3


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-01 18:34 Adding a new thread model to GCC LIU Hao
@ 2022-10-01 20:02 ` Bernhard Reutner-Fischer
  2022-10-02 12:54   ` LIU Hao
  2022-10-21  9:58 ` Jonathan Wakely
  1 sibling, 1 reply; 58+ messages in thread
From: Bernhard Reutner-Fischer @ 2022-10-01 20:02 UTC (permalink / raw)
  To: LIU Hao, LIU Hao via Gcc-patches, gcc-patches, libstdc++; +Cc: fortran

On 1 October 2022 20:34:45 CEST, LIU Hao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>Greetings.

>The first patch is necessary because somewhere in libgfortran, `pthread_t` is referenced. If the thread model is not `posix`, it fails to compile.

One of several shortcomings mentioned already on Sun, 02 Sep 2018 15:40:28 -0700 in
https://www.mail-archive.com/gcc-patches@gcc.gnu.org/msg196212.html



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-01 20:02 ` Bernhard Reutner-Fischer
@ 2022-10-02 12:54   ` LIU Hao
  2022-10-03  5:03     ` Bernhard Reutner-Fischer
  0 siblings, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-02 12:54 UTC (permalink / raw)
  To: Bernhard Reutner-Fischer, LIU Hao via Gcc-patches; +Cc: fortran


[-- Attachment #1.1: Type: text/plain, Size: 936 bytes --]

在 2022-10-02 04:02, Bernhard Reutner-Fischer 写道:
> On 1 October 2022 20:34:45 CEST, LIU Hao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>> Greetings.
> 
>> The first patch is necessary because somewhere in libgfortran, `pthread_t` is referenced. If the thread model is not `posix`, it fails to compile.
> 
> One of several shortcomings mentioned already on Sun, 02 Sep 2018 15:40:28 -0700 in
> https://www.mail-archive.com/gcc-patches@gcc.gnu.org/msg196212.html
> 

Forgive me but I didn't get your point. Is the 'shortcoming' the fact that `pthread_t` must be 
preferred to `__gthread_t`?

For non-posix thread models, <pthread.h> is not included, so `pthread_t` is not declared. I haven't 
looked at other code in libgfortran, but changing `pthread_t` to `__gthread_t` does allow 
libgfortran to build. I don't know how to test it though, as I don't write Fortran myself.


-- 
Best regards,
LIU Hao


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-02 12:54   ` LIU Hao
@ 2022-10-03  5:03     ` Bernhard Reutner-Fischer
  2022-10-04  8:06       ` LIU Hao
  2022-10-04 12:44       ` LIU Hao
  0 siblings, 2 replies; 58+ messages in thread
From: Bernhard Reutner-Fischer @ 2022-10-03  5:03 UTC (permalink / raw)
  To: LIU Hao, LIU Hao via Gcc-patches; +Cc: fortran

On 2 October 2022 14:54:54 CEST, LIU Hao <lh_mouse@126.com> wrote:
>在 2022-10-02 04:02, Bernhard Reutner-Fischer 写道:
>> On 1 October 2022 20:34:45 CEST, LIU Hao via Gcc-patches <gcc-patches@gcc.gnu.org> wrote:
>>> Greetings.
>> 
>>> The first patch is necessary because somewhere in libgfortran, `pthread_t` is referenced. If the thread model is not `posix`, it fails to compile.
>> 
>> One of several shortcomings mentioned already on Sun, 02 Sep 2018 15:40:28 -0700 in
>> https://www.mail-archive.com/gcc-patches@gcc.gnu.org/msg196212.html
>> 
>
>Forgive me but I didn't get your point. Is the 'shortcoming' the fact that `pthread_t` must be preferred to `__gthread_t`?

No, sorry for my brevity.
Using __gthread_t like in your patch is correct.

thanks,

>
>For non-posix thread models, <pthread.h> is not included, so `pthread_t` is not declared. I haven't looked at other code in libgfortran, but changing `pthread_t` to `__gthread_t` does allow libgfortran to build. I don't know how to test it though, as I don't write Fortran myself.
>
>


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-03  5:03     ` Bernhard Reutner-Fischer
@ 2022-10-04  8:06       ` LIU Hao
  2022-10-04 19:45         ` Bernhard Reutner-Fischer
  2022-10-04 12:44       ` LIU Hao
  1 sibling, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-04  8:06 UTC (permalink / raw)
  To: Bernhard Reutner-Fischer, LIU Hao via Gcc-patches; +Cc: fortran


[-- Attachment #1.1: Type: text/plain, Size: 558 bytes --]

在 2022-10-03 13:03, Bernhard Reutner-Fischer 写道:
> 
> No, sorry for my brevity.
> Using __gthread_t like in your patch is correct.
> 

I see. In 'libgfortran/io/async.c' there is

   ```
     async_unit *au = u->au;
     LOCK (&au->lock);
     thread_unit = u;
     au->thread = __gthread_self ();
   ```

so indeed `thread` should be `__gthread_t`. By the way I reported this issue four months ago and 
haven't received any response so far:

   https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105764


-- 
Best regards,
LIU Hao


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-03  5:03     ` Bernhard Reutner-Fischer
  2022-10-04  8:06       ` LIU Hao
@ 2022-10-04 12:44       ` LIU Hao
  2022-10-04 13:13         ` Xi Ruoyao
  2022-10-10 15:56         ` LIU Hao
  1 sibling, 2 replies; 58+ messages in thread
From: LIU Hao @ 2022-10-04 12:44 UTC (permalink / raw)
  To: gcc-patches; +Cc: 10walls


[-- Attachment #1.1.1: Type: text/plain, Size: 828 bytes --]

Attached are revised patches. These are exported from trunk.


There is a change since my last message:

   * A new Makefile variable `SHLIB_MCFGTHREAD_LIBS` has been introduced, to keep
     the other thread models from being affected.


After applying these patches, configure scripts in these subdirectories need to be regenerated:

   * gcc
   * libgcc
   * libatomic
   * libstdc++-v3


The patch for libgfortran fixes

   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105764


I have successfully bootstrapped GCC 12 with these patches, on i686-w64-mingw32 (with MSVCRT) and 
x86_64-w64-mingw32 (with MSVCRT and UCRT). No errors have been observed so far.

Once these patches land in GCC, we can start the work in mingw-w64 basing on `__USING_MCFGTHREAD__`.



-- 
Best regards,
LIU Hao


[-- Attachment #1.1.2: 0001-libgfortran-Use-__gthread_t-instead-of-pthread_t.patch --]
[-- Type: text/plain, Size: 970 bytes --]

From e1ab15fc95ac8180156feed410cacb64a41a9567 Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Fri, 27 May 2022 23:12:48 +0800
Subject: [PATCH 1/3] libgfortran: Use `__gthread_t` instead of `pthread_t`

It used to cause errors if a thread model other than `posix` was selected,
which looks like a leftover from a79878585a1c5e32bafbc6d1e73f91fd6e4293bf.

libgfortran/ChangeLog:
	* io/async.h (struct async_unit): Use `__gthread_t` instead
	of `pthread_t`.

---
 libgfortran/io/async.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libgfortran/io/async.h b/libgfortran/io/async.h
index efd542a45e82..d57722a95e44 100644
--- a/libgfortran/io/async.h
+++ b/libgfortran/io/async.h
@@ -351,7 +351,7 @@ typedef struct async_unit
   struct adv_cond work;
   struct adv_cond emptysignal;
   struct st_parameter_dt *pdt;
-  pthread_t thread;
+  __gthread_t thread;
   struct transfer_queue *head;
   struct transfer_queue *tail;
 
-- 
2.37.3


[-- Attachment #1.1.3: 0002-libstdc-thread-Implement-_GLIBCXX_NPROCS-for-Windows.patch --]
[-- Type: text/plain, Size: 1167 bytes --]

From 0376949aae74b92a7ba327881672e038c3c0d825 Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Sun, 2 Oct 2022 00:57:08 +0800
Subject: [PATCH 2/3] libstdc++/thread: Implement `_GLIBCXX_NPROCS` for Windows

This makes `std::thread::hardware_concurrency()` return the number of
logical processors, instead of zero.

libstdc++-v3/ChangeLog:
	* src/c++11/thread.cc (get_nprocs): Add new implementation
	for native Windows targets

---
 libstdc++-v3/src/c++11/thread.cc | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc
index 707a4ad415b9..b39d9f4a9e29 100644
--- a/libstdc++-v3/src/c++11/thread.cc
+++ b/libstdc++-v3/src/c++11/thread.cc
@@ -68,6 +68,15 @@ static inline int get_nprocs()
 #elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
 # include <unistd.h>
 # define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
+#elif defined(_WIN32)
+# include <windows.h>
+static inline int get_nprocs()
+{
+  SYSTEM_INFO sysinfo;
+  GetSystemInfo(&sysinfo);
+  return (int)sysinfo.dwNumberOfProcessors;
+}
+# define _GLIBCXX_NPROCS get_nprocs()
 #else
 # define _GLIBCXX_NPROCS 0
 #endif
-- 
2.37.3


[-- Attachment #1.1.4: 0003-gcc-Add-mcf-thread-model-support-from-mcfgthread.patch --]
[-- Type: text/plain, Size: 9629 bytes --]

From d69cbaca07cd7b0e2d725574c8d5913b1c5e0bd5 Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Sat, 16 Apr 2022 00:46:23 +0800
Subject: [PATCH 3/3] gcc: Add 'mcf' thread model support from mcfgthread

This patch adds the new thread model `mcf`, which implements mutexes
and condition variables with the mcfgthread library.

Source code for mcfgthread is available at <https://github.com/lhmouse/mcfgthread>.

config/ChangeLog:
	* gthr.m4 (GCC_AC_THREAD_HEADER): Add new case for `mcf` thread
	model

gcc/config/ChangeLog:
	* i386/mingw-mcfgthread.h: New file
	* i386/mingw32.h: Add builtin macro and default libraries for
	mcfgthread when thread model is `mcf`

gcc/ChangeLog:
	* config.gcc: Include 'i386/mingw-mcfgthread.h' when thread model
	is `mcf`
	* configure.ac: Recognize `mcf` as a valid thread model

libatomic/ChangeLog:
	* configure.tgt: Add new case for `mcf` thread model

libgcc/ChangeLog:
	* config.host: Add new cases for `mcf` thread model
	* config/i386/gthr-mcf.h: New file
	* config/i386/t-mingw-mcfgthread: New file
	* config/i386/t-slibgcc-cygming: Add mcfgthread for libgcc DLL

libstdc++-v3/ChangeLog:
	* libsupc++/atexit_thread.cc (__cxa_thread_atexit): Use
	implementation from mcfgthread if available
	* libsupc++/guard.cc (__cxa_guard_acquire, __cxa_guard_release,
	__cxa_guard_abort): Use implementations from mcfgthread if
	available

---
 config/gthr.m4                          |  1 +
 gcc/config.gcc                          |  3 +++
 gcc/config/i386/mingw-mcfgthread.h      |  1 +
 gcc/config/i386/mingw32.h               | 11 ++++++++-
 gcc/configure.ac                        |  2 +-
 libatomic/configure.tgt                 |  2 +-
 libgcc/config.host                      |  6 +++++
 libgcc/config/i386/gthr-mcf.h           |  1 +
 libgcc/config/i386/t-mingw-mcfgthread   |  1 +
 libgcc/config/i386/t-slibgcc-cygming    |  6 ++++-
 libstdc++-v3/libsupc++/atexit_thread.cc | 20 ++++++++++++++++
 libstdc++-v3/libsupc++/guard.cc         | 31 +++++++++++++++++++++++++
 12 files changed, 81 insertions(+), 4 deletions(-)
 create mode 100644 gcc/config/i386/mingw-mcfgthread.h
 create mode 100644 libgcc/config/i386/gthr-mcf.h
 create mode 100644 libgcc/config/i386/t-mingw-mcfgthread

diff --git a/config/gthr.m4 b/config/gthr.m4
index 4b937306ad08..11996247f150 100644
--- a/config/gthr.m4
+++ b/config/gthr.m4
@@ -22,6 +22,7 @@ case $1 in
     tpf)	thread_header=config/s390/gthr-tpf.h ;;
     vxworks)	thread_header=config/gthr-vxworks.h ;;
     win32)	thread_header=config/i386/gthr-win32.h ;;
+    mcf)	thread_header=config/i386/gthr-mcf.h ;;
 esac
 AC_SUBST(thread_header)
 ])
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 35dfc00fe4d9..d82396f50309 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2090,6 +2090,9 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	if test x$enable_threads = xposix ; then
 		tm_file="${tm_file} i386/mingw-pthread.h"
 	fi
+	if test x$enable_threads = xmcf ; then
+		tm_file="${tm_file} i386/mingw-mcfgthread.h"
+	fi
 	tm_file="${tm_file} i386/mingw32.h"
 	# This makes the logic if mingw's or the w64 feature set has to be used
 	case ${target} in
diff --git a/gcc/config/i386/mingw-mcfgthread.h b/gcc/config/i386/mingw-mcfgthread.h
new file mode 100644
index 000000000000..ec381a7798f1
--- /dev/null
+++ b/gcc/config/i386/mingw-mcfgthread.h
@@ -0,0 +1 @@
+#define TARGET_USE_MCFGTHREAD 1
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index d3ca0cd0279d..307a803b92c2 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -32,6 +32,14 @@ along with GCC; see the file COPYING3.  If not see
 	 | MASK_STACK_PROBE | MASK_ALIGN_DOUBLE \
 	 | MASK_MS_BITFIELD_LAYOUT)
 
+#ifndef TARGET_USE_MCFGTHREAD
+#define CPP_MCFGTHREAD()  ((void)0)
+#define LIB_MCFGTHREAD     ""
+#else
+#define CPP_MCFGTHREAD()  (builtin_define("__USING_MCFGTHREAD__"))
+#define LIB_MCFGTHREAD     " -lmcfgthread "
+#endif
+
 /* See i386/crtdll.h for an alternative definition. _INTEGRAL_MAX_BITS
    is for compatibility with native compiler.  */
 #define EXTRA_OS_CPP_BUILTINS()					\
@@ -50,6 +58,7 @@ along with GCC; see the file COPYING3.  If not see
 	  builtin_define_std ("WIN64");				\
 	  builtin_define ("_WIN64");				\
 	}							\
+	CPP_MCFGTHREAD();	\
     }								\
   while (0)
 
@@ -185,7 +194,7 @@ along with GCC; see the file COPYING3.  If not see
 #define REAL_LIBGCC_SPEC \
   "%{mthreads:-lmingwthrd} -lmingw32 \
    " SHARED_LIBGCC_SPEC " \
-   -lmoldname -lmingwex -lmsvcrt -lkernel32"
+   -lmoldname -lmingwex -lmsvcrt " LIB_MCFGTHREAD " -lkernel32 -lntdll"
 
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
diff --git a/gcc/configure.ac b/gcc/configure.ac
index b6bafa8b7d69..0641b8a61dae 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1991,7 +1991,7 @@ case ${enable_threads} in
     target_thread_file='single'
     ;;
   aix | dce | lynx | mipssde | posix | rtems | \
-  single | tpf | vxworks | win32)
+  single | tpf | vxworks | win32 | mcf)
     target_thread_file=${enable_threads}
     ;;
   *)
diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
index 33f8c91ce771..86a59475b6e7 100644
--- a/libatomic/configure.tgt
+++ b/libatomic/configure.tgt
@@ -159,7 +159,7 @@ case "${target}" in
   *-*-mingw*)
 	# OS support for atomic primitives.
         case ${target_thread_file} in
-          win32)
+          win32 | mcf)
             config_path="${config_path} mingw"
             ;;
           posix)
diff --git a/libgcc/config.host b/libgcc/config.host
index 9dcc2538dc86..44a8218a31d3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -825,6 +825,9 @@ i[34567]86-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
@@ -849,6 +852,9 @@ x86_64-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
diff --git a/libgcc/config/i386/gthr-mcf.h b/libgcc/config/i386/gthr-mcf.h
new file mode 100644
index 000000000000..58131bb7ca92
--- /dev/null
+++ b/libgcc/config/i386/gthr-mcf.h
@@ -0,0 +1 @@
+#include <mcfgthread/gthr.h>
diff --git a/libgcc/config/i386/t-mingw-mcfgthread b/libgcc/config/i386/t-mingw-mcfgthread
new file mode 100644
index 000000000000..c5b817f09b71
--- /dev/null
+++ b/libgcc/config/i386/t-mingw-mcfgthread
@@ -0,0 +1 @@
+SHLIB_MCFGTHREAD_LIBS = -lmcfgthread -lkernel32 -lntdll
diff --git a/libgcc/config/i386/t-slibgcc-cygming b/libgcc/config/i386/t-slibgcc-cygming
index 6236c78e4668..6871498cf60e 100644
--- a/libgcc/config/i386/t-slibgcc-cygming
+++ b/libgcc/config/i386/t-slibgcc-cygming
@@ -27,6 +27,9 @@ endif
 ifndef SHLIB_PTHREAD_LDFLAG
 SHLIB_PTHREAD_LDFLAG =
 endif
+ifndef SHLIB_MCFGTHREAD_LIBS
+SHLIB_MCFGTHREAD_LIBS =
+endif
 
 SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
 	if [ ! -d $(SHLIB_DIR) ]; then \
@@ -37,7 +40,8 @@ SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
 	$(SHLIB_MAP).def \
 	-Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \
 	-o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
-	$(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) && \
+	$(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) \
+	$(SHLIB_MCFGTHREAD_LIBS) && \
 	if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
 	  mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
 		$(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
diff --git a/libstdc++-v3/libsupc++/atexit_thread.cc b/libstdc++-v3/libsupc++/atexit_thread.cc
index a2693d0424e1..2f936ab02ce2 100644
--- a/libstdc++-v3/libsupc++/atexit_thread.cc
+++ b/libstdc++-v3/libsupc++/atexit_thread.cc
@@ -25,6 +25,24 @@
 #include <cstdlib>
 #include <new>
 #include "bits/gthr.h"
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
+		     void *obj, void *dso_handle) _GLIBCXX_NOTHROW
+{
+  return __MCF_cxa_thread_atexit (dtor, obj, dso_handle);
+}
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
@@ -173,3 +191,5 @@ __cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
 }
 
 #endif /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */
+
+#endif // __USING_MCFGTHREAD__
diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc
index abb57117cdfd..0f81a22c6845 100644
--- a/libstdc++-v3/libsupc++/guard.cc
+++ b/libstdc++-v3/libsupc++/guard.cc
@@ -28,6 +28,35 @@
 #include <cxxabi.h>
 #include <exception>
 #include <new>
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_guard_acquire (__guard* g) _GLIBCXX_NOTHROW
+  {
+    return __MCF_cxa_guard_acquire(g);
+  }
+
+extern "C" void
+__cxa_guard_release (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_release(g);
+  }
+
+extern "C" void
+__cxa_guard_abort (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_abort(g);
+  }
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #include <ext/atomicity.h>
 #include <ext/concurrence.h>
 #include <bits/atomic_lockfree_defines.h>
@@ -458,3 +487,5 @@ namespace __cxxabiv1
 #endif
   }
 }
+
+#endif // __USING_MCFGTHREAD__
-- 
2.37.3


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-04 12:44       ` LIU Hao
@ 2022-10-04 13:13         ` Xi Ruoyao
  2022-10-04 13:45           ` LIU Hao
  2022-10-10 15:56         ` LIU Hao
  1 sibling, 1 reply; 58+ messages in thread
From: Xi Ruoyao @ 2022-10-04 13:13 UTC (permalink / raw)
  To: LIU Hao; +Cc: gcc-patches

I don't really understand MinGW, but some "non-technical" things:

On Tue, 2022-10-04 at 20:44 +0800, LIU Hao via Gcc-patches wrote:
> After applying these patches, configure scripts in these
> subdirectories need to be regenerated:
> 
>    * gcc
>    * libgcc
>    * libatomic
>    * libstdc++-v3

In GCC development we usually include the configure regeneration in the
patch because the scripts are also version controlled.

> The patch for libgfortran fixes
> 
>    * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105764

It's better to include the ID in the subject and ChangeLog of the patch.
Like:

   [PATCH 1/3] libgfortran: Use `__gthread_t` instead of `pthread_t` [PR 105764]
   
   It used to cause errors if a thread model other than `posix` was selected,
   which looks like a leftover from a79878585a1c5e32bafbc6d1e73f91fd6e4293bf.
   
   libgfortran/ChangeLog:
   
   	PR libgfortran/105764
   	* io/async.h (struct async_unit): Use `__gthread_t` instead
   	of `pthread_t`.

This allows a git hook to append a message into the PR 105764 entry in
bugzilla once the patch is committed into trunk.

Normally I leave an empty line after "ChangeLog:" but I'm not sure if
it's strictly needed.

> gcc/config/ChangeLog:
> 	* i386/mingw-mcfgthread.h: New file
> 	* i386/mingw32.h: Add builtin macro and default libraries for
> 	mcfgthread when thread model is `mcf`

Normally I leave a "." for each ChangeLog entry, but I'm not sure if
it's strictly needed.  However there is no gcc/config/ChangeLog, use
gcc/ChangeLog instead.

And, from https://gcc.gnu.org/contribute.html#patches:

"It is strongly discouraged to post patches as MIME parts of type
application/whatever, disposition attachment or encoded as base64 or
quoted-printable."

Just try "git send-email", it will do the correct thing.  Mimicking its
behavior in a mail client is also possible but error-prune (the mail
client can destroy your patch by replacing your tabs with spaces, etc.)

-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-04 13:13         ` Xi Ruoyao
@ 2022-10-04 13:45           ` LIU Hao
  2022-10-05  1:23             ` Xi Ruoyao
  0 siblings, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-04 13:45 UTC (permalink / raw)
  To: Xi Ruoyao; +Cc: gcc-patches


[-- Attachment #1.1: Type: text/plain, Size: 2132 bytes --]

在 2022-10-04 21:13, Xi Ruoyao 写道:
> 
> In GCC development we usually include the configure regeneration in the
> patch because the scripts are also version controlled.
> 

There is a reason for not doing that: Generated contents can't be reviewed.

In mingw-w64 we do the opposite: The person who commits a patch is responsible for update configure, 
Makefile.in, etc. The patch itself doesn't include generated contents.


> It's better to include the ID in the subject and ChangeLog of the patch.
> Like:
> 
>     [PATCH 1/3] libgfortran: Use `__gthread_t` instead of `pthread_t` [PR 105764]
>     
>     It used to cause errors if a thread model other than `posix` was selected,
>     which looks like a leftover from a79878585a1c5e32bafbc6d1e73f91fd6e4293bf.
>     
>     libgfortran/ChangeLog:
>     
>     	PR libgfortran/105764
>     	* io/async.h (struct async_unit): Use `__gthread_t` instead
>     	of `pthread_t`.
> 

Yes I think this change is good.


> 
> And, from https://gcc.gnu.org/contribute.html#patches:
> 
> "It is strongly discouraged to post patches as MIME parts of type
> application/whatever, disposition attachment or encoded as base64 or
> quoted-printable."
> 
> Just try "git send-email", it will do the correct thing.  Mimicking its
> behavior in a mail client is also possible but error-prune (the mail
> client can destroy your patch by replacing your tabs with spaces, etc.)
> 

It's 'discouraged'. It is not forbidden. I expect everywhere people who receive emails to accept 
attachments. Thunderbird has a nice feature to display text attachments inline, so there is no need 
to download it and open it with an external editor, or whatever.


And, I never get `git send-mail` work on my machine:

    ```
    Send this email? ([y]es|[n]o|[e]dit|[q]uit|[a]ll): y
    Unable to initialize SMTP properly. Check config and use --smtp-debug. VA
    LUES: server=smtp.126.com encryption=tls hello=localhost.localdomain port
    =465 at /usr/lib/git-core/git-send-email line 1684, <FIN> line 3.
    ```




-- 
Best regards,
LIU Hao


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-04  8:06       ` LIU Hao
@ 2022-10-04 19:45         ` Bernhard Reutner-Fischer
  0 siblings, 0 replies; 58+ messages in thread
From: Bernhard Reutner-Fischer @ 2022-10-04 19:45 UTC (permalink / raw)
  To: LIU Hao, LIU Hao via Gcc-patches; +Cc: fortran

On 4 October 2022 10:06:00 CEST, LIU Hao <lh_mouse@126.com> wrote:
>在 2022-10-03 13:03, Bernhard Reutner-Fischer 写道:
>> 
>> No, sorry for my brevity.
>> Using __gthread_t like in your patch is correct.
>> 
>
>I see. In 'libgfortran/io/async.c' there is
>
>  ```
>    async_unit *au = u->au;
>    LOCK (&au->lock);
>    thread_unit = u;
>    au->thread = __gthread_self ();
>  ```
>
>so indeed `thread` should be `__gthread_t`.

Yes.

> By the way I reported this issue four months ago and haven't received any response so far:
>
>  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105764

So, ideally, you would mention this PR in your patch.

LGTM (obvious even) but I cannot formally approve it.
thanks,

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-04 13:45           ` LIU Hao
@ 2022-10-05  1:23             ` Xi Ruoyao
  0 siblings, 0 replies; 58+ messages in thread
From: Xi Ruoyao @ 2022-10-05  1:23 UTC (permalink / raw)
  To: LIU Hao; +Cc: gcc-patches

On Tue, 2022-10-04 at 21:45 +0800, LIU Hao wrote:
> 在 2022-10-04 21:13, Xi Ruoyao 写道:
> > 
> > In GCC development we usually include the configure regeneration in the
> > patch because the scripts are also version controlled.
> > 
> 
> There is a reason for not doing that: Generated contents can't be reviewed.
> 
> In mingw-w64 we do the opposite: The person who commits a patch is responsible for update configure, 
> Makefile.in, etc. The patch itself doesn't include generated contents.

The reviewer can simply skip the changes in configure.  But including
the configure allows the potential testers to test the change without
autoconf-2.69 installed.

Maybe we can make a compromise: put the line "configure: Regenerate." in
the ChangeLog, but do not actually include the change.  Now if the
committer forgot to regenerate it, the git hook will reject the push
immediately.

(Just my 2 cents.)
-- 
Xi Ruoyao <xry111@xry111.site>
School of Aerospace Science and Technology, Xidian University

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-04 12:44       ` LIU Hao
  2022-10-04 13:13         ` Xi Ruoyao
@ 2022-10-10 15:56         ` LIU Hao
  2022-10-11 13:22           ` LIU Hao
  1 sibling, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-10 15:56 UTC (permalink / raw)
  To: gcc-patches; +Cc: 10walls


[-- Attachment #1.1.1: Type: text/plain, Size: 910 bytes --]

在 2022-10-04 20:44, LIU Hao 写道:
> Attached are revised patches. These are exported from trunk.
> 

Revised further. The patch for libgfortran has been committed to trunk today, so I include only the 
other two.

   * In the second patch, a space character has been inserted after
     `(int)` for clearness.

   * The macro controlling how to build GCC itself has been renamed to
     `TARGET_USING_MCFGTHREAD` for consistency.

   * Checks against `TARGET_USING_MCFGTHREAD` have been updated in a
     more friendly way.

   * When not using mcfgthread, NTDLL is no longer a default library.
     Although all recent Windows versions are based on the NT kernel,
     there could still be people who want to target 9x or CE; thus
     NTDLL is only added when it is potentially necessary, for example
     when linking against the static libgcc.



-- 
Best regards,
LIU Hao


[-- Attachment #1.1.2: 0001-libstdc-thread-Implement-_GLIBCXX_NPROCS-for-Windows.patch --]
[-- Type: text/plain, Size: 1167 bytes --]

From b371849927adba290d1e17e2a43866cc3465eb4c Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Sun, 2 Oct 2022 00:57:08 +0800
Subject: [PATCH 1/2] libstdc++/thread: Implement `_GLIBCXX_NPROCS` for Windows

This makes `std::thread::hardware_concurrency()` return the number of
logical processors, instead of zero.

libstdc++-v3/ChangeLog:
	* src/c++11/thread.cc (get_nprocs): Add new implementation
	for native Windows targets
---
 libstdc++-v3/src/c++11/thread.cc | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc
index 707a4ad415b9..a54bc3e939a0 100644
--- a/libstdc++-v3/src/c++11/thread.cc
+++ b/libstdc++-v3/src/c++11/thread.cc
@@ -68,6 +68,15 @@ static inline int get_nprocs()
 #elif defined(_GLIBCXX_USE_SC_NPROC_ONLN)
 # include <unistd.h>
 # define _GLIBCXX_NPROCS sysconf(_SC_NPROC_ONLN)
+#elif defined(_WIN32)
+# include <windows.h>
+static inline int get_nprocs()
+{
+  SYSTEM_INFO sysinfo;
+  GetSystemInfo(&sysinfo);
+  return (int) sysinfo.dwNumberOfProcessors;
+}
+# define _GLIBCXX_NPROCS get_nprocs()
 #else
 # define _GLIBCXX_NPROCS 0
 #endif
-- 
2.37.3


[-- Attachment #1.1.3: 0002-gcc-Add-mcf-thread-model-support-from-mcfgthread.patch --]
[-- Type: text/plain, Size: 9753 bytes --]

From 5df9fa2b8d6ea3c357e7a9fcd42721811ea376ce Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Sat, 16 Apr 2022 00:46:23 +0800
Subject: [PATCH 2/2] gcc: Add 'mcf' thread model support from mcfgthread

This patch adds the new thread model `mcf`, which implements mutexes
and condition variables with the mcfgthread library.

Source code for mcfgthread is available at <https://github.com/lhmouse/mcfgthread>.

config/ChangeLog:
	* gthr.m4 (GCC_AC_THREAD_HEADER): Add new case for `mcf` thread
	model

gcc/config/ChangeLog:
	* i386/mingw-mcfgthread.h: New file
	* i386/mingw32.h: Add builtin macro and default libraries for
	mcfgthread when thread model is `mcf`

gcc/ChangeLog:
	* config.gcc: Include 'i386/mingw-mcfgthread.h' when thread model
	is `mcf`
	* configure.ac: Recognize `mcf` as a valid thread model

libatomic/ChangeLog:
	* configure.tgt: Add new case for `mcf` thread model

libgcc/ChangeLog:
	* config.host: Add new cases for `mcf` thread model
	* config/i386/gthr-mcf.h: New file
	* config/i386/t-mingw-mcfgthread: New file
	* config/i386/t-slibgcc-cygming: Add mcfgthread for libgcc DLL

libstdc++-v3/ChangeLog:
	* libsupc++/atexit_thread.cc (__cxa_thread_atexit): Use
	implementation from mcfgthread if available
	* libsupc++/guard.cc (__cxa_guard_acquire, __cxa_guard_release,
	__cxa_guard_abort): Use implementations from mcfgthread if
	available
---
 config/gthr.m4                          |  1 +
 gcc/config.gcc                          |  3 +++
 gcc/config/i386/mingw-mcfgthread.h      |  1 +
 gcc/config/i386/mingw32.h               | 13 ++++++++++-
 gcc/configure.ac                        |  2 +-
 libatomic/configure.tgt                 |  2 +-
 libgcc/config.host                      |  6 +++++
 libgcc/config/i386/gthr-mcf.h           |  1 +
 libgcc/config/i386/t-mingw-mcfgthread   |  1 +
 libgcc/config/i386/t-slibgcc-cygming    |  6 ++++-
 libstdc++-v3/libsupc++/atexit_thread.cc | 20 ++++++++++++++++
 libstdc++-v3/libsupc++/guard.cc         | 31 +++++++++++++++++++++++++
 12 files changed, 83 insertions(+), 4 deletions(-)
 create mode 100644 gcc/config/i386/mingw-mcfgthread.h
 create mode 100644 libgcc/config/i386/gthr-mcf.h
 create mode 100644 libgcc/config/i386/t-mingw-mcfgthread

diff --git a/config/gthr.m4 b/config/gthr.m4
index 4b937306ad08..11996247f150 100644
--- a/config/gthr.m4
+++ b/config/gthr.m4
@@ -22,6 +22,7 @@ case $1 in
     tpf)	thread_header=config/s390/gthr-tpf.h ;;
     vxworks)	thread_header=config/gthr-vxworks.h ;;
     win32)	thread_header=config/i386/gthr-win32.h ;;
+    mcf)	thread_header=config/i386/gthr-mcf.h ;;
 esac
 AC_SUBST(thread_header)
 ])
diff --git a/gcc/config.gcc b/gcc/config.gcc
index eec544ff1bac..1f6adea1ab9b 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2091,6 +2091,9 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	if test x$enable_threads = xposix ; then
 		tm_file="${tm_file} i386/mingw-pthread.h"
 	fi
+	if test x$enable_threads = xmcf ; then
+		tm_file="${tm_file} i386/mingw-mcfgthread.h"
+	fi
 	tm_file="${tm_file} i386/mingw32.h"
 	# This makes the logic if mingw's or the w64 feature set has to be used
 	case ${target} in
diff --git a/gcc/config/i386/mingw-mcfgthread.h b/gcc/config/i386/mingw-mcfgthread.h
new file mode 100644
index 000000000000..7d4eda3ed494
--- /dev/null
+++ b/gcc/config/i386/mingw-mcfgthread.h
@@ -0,0 +1 @@
+#define TARGET_USING_MCFGTHREAD  1
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index d3ca0cd0279d..b5f31c3da0ac 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -32,6 +32,10 @@ along with GCC; see the file COPYING3.  If not see
 	 | MASK_STACK_PROBE | MASK_ALIGN_DOUBLE \
 	 | MASK_MS_BITFIELD_LAYOUT)
 
+#ifndef TARGET_USING_MCFGTHREAD
+#define TARGET_USING_MCFGTHREAD  0
+#endif
+
 /* See i386/crtdll.h for an alternative definition. _INTEGRAL_MAX_BITS
    is for compatibility with native compiler.  */
 #define EXTRA_OS_CPP_BUILTINS()					\
@@ -50,6 +54,8 @@ along with GCC; see the file COPYING3.  If not see
 	  builtin_define_std ("WIN64");				\
 	  builtin_define ("_WIN64");				\
 	}							\
+      if (TARGET_USING_MCFGTHREAD)				\
+	builtin_define ("__USING_MCFGTHREAD__");		\
     }								\
   while (0)
 
@@ -181,11 +187,16 @@ along with GCC; see the file COPYING3.  If not see
 #else
 #define SHARED_LIBGCC_SPEC " -lgcc "
 #endif
+#if TARGET_USING_MCFGTHREAD
+#define MCFGTHREAD_SPEC  " -lmcfgthread -lkernel32 -lntdll "
+#else
+#define MCFGTHREAD_SPEC  ""
+#endif
 #undef REAL_LIBGCC_SPEC
 #define REAL_LIBGCC_SPEC \
   "%{mthreads:-lmingwthrd} -lmingw32 \
    " SHARED_LIBGCC_SPEC " \
-   -lmoldname -lmingwex -lmsvcrt -lkernel32"
+   -lmoldname -lmingwex -lmsvcrt -lkernel32 " MCFGTHREAD_SPEC
 
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
diff --git a/gcc/configure.ac b/gcc/configure.ac
index e48fcbfe18ea..e1ef2ecf0267 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1991,7 +1991,7 @@ case ${enable_threads} in
     target_thread_file='single'
     ;;
   aix | dce | lynx | mipssde | posix | rtems | \
-  single | tpf | vxworks | win32)
+  single | tpf | vxworks | win32 | mcf)
     target_thread_file=${enable_threads}
     ;;
   *)
diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
index 33f8c91ce771..86a59475b6e7 100644
--- a/libatomic/configure.tgt
+++ b/libatomic/configure.tgt
@@ -159,7 +159,7 @@ case "${target}" in
   *-*-mingw*)
 	# OS support for atomic primitives.
         case ${target_thread_file} in
-          win32)
+          win32 | mcf)
             config_path="${config_path} mingw"
             ;;
           posix)
diff --git a/libgcc/config.host b/libgcc/config.host
index 9dcc2538dc86..44a8218a31d3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -825,6 +825,9 @@ i[34567]86-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
@@ -849,6 +852,9 @@ x86_64-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
diff --git a/libgcc/config/i386/gthr-mcf.h b/libgcc/config/i386/gthr-mcf.h
new file mode 100644
index 000000000000..58131bb7ca92
--- /dev/null
+++ b/libgcc/config/i386/gthr-mcf.h
@@ -0,0 +1 @@
+#include <mcfgthread/gthr.h>
diff --git a/libgcc/config/i386/t-mingw-mcfgthread b/libgcc/config/i386/t-mingw-mcfgthread
new file mode 100644
index 000000000000..c5b817f09b71
--- /dev/null
+++ b/libgcc/config/i386/t-mingw-mcfgthread
@@ -0,0 +1 @@
+SHLIB_MCFGTHREAD_LIBS = -lmcfgthread -lkernel32 -lntdll
diff --git a/libgcc/config/i386/t-slibgcc-cygming b/libgcc/config/i386/t-slibgcc-cygming
index 6236c78e4668..6871498cf60e 100644
--- a/libgcc/config/i386/t-slibgcc-cygming
+++ b/libgcc/config/i386/t-slibgcc-cygming
@@ -27,6 +27,9 @@ endif
 ifndef SHLIB_PTHREAD_LDFLAG
 SHLIB_PTHREAD_LDFLAG =
 endif
+ifndef SHLIB_MCFGTHREAD_LIBS
+SHLIB_MCFGTHREAD_LIBS =
+endif
 
 SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
 	if [ ! -d $(SHLIB_DIR) ]; then \
@@ -37,7 +40,8 @@ SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
 	$(SHLIB_MAP).def \
 	-Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \
 	-o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
-	$(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) && \
+	$(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) \
+	$(SHLIB_MCFGTHREAD_LIBS) && \
 	if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
 	  mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
 		$(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
diff --git a/libstdc++-v3/libsupc++/atexit_thread.cc b/libstdc++-v3/libsupc++/atexit_thread.cc
index a2693d0424e1..2f936ab02ce2 100644
--- a/libstdc++-v3/libsupc++/atexit_thread.cc
+++ b/libstdc++-v3/libsupc++/atexit_thread.cc
@@ -25,6 +25,24 @@
 #include <cstdlib>
 #include <new>
 #include "bits/gthr.h"
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
+		     void *obj, void *dso_handle) _GLIBCXX_NOTHROW
+{
+  return __MCF_cxa_thread_atexit (dtor, obj, dso_handle);
+}
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
@@ -173,3 +191,5 @@ __cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
 }
 
 #endif /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */
+
+#endif // __USING_MCFGTHREAD__
diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc
index abb57117cdfd..0f81a22c6845 100644
--- a/libstdc++-v3/libsupc++/guard.cc
+++ b/libstdc++-v3/libsupc++/guard.cc
@@ -28,6 +28,35 @@
 #include <cxxabi.h>
 #include <exception>
 #include <new>
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_guard_acquire (__guard* g) _GLIBCXX_NOTHROW
+  {
+    return __MCF_cxa_guard_acquire(g);
+  }
+
+extern "C" void
+__cxa_guard_release (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_release(g);
+  }
+
+extern "C" void
+__cxa_guard_abort (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_abort(g);
+  }
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #include <ext/atomicity.h>
 #include <ext/concurrence.h>
 #include <bits/atomic_lockfree_defines.h>
@@ -458,3 +487,5 @@ namespace __cxxabiv1
 #endif
   }
 }
+
+#endif // __USING_MCFGTHREAD__
-- 
2.37.3


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-10 15:56         ` LIU Hao
@ 2022-10-11 13:22           ` LIU Hao
  2022-10-14  9:39             ` Jonathan Yong
  0 siblings, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-11 13:22 UTC (permalink / raw)
  To: gcc-patches; +Cc: 10walls


[-- Attachment #1.1.1: Type: text/plain, Size: 1098 bytes --]

在 2022-10-10 23:56, LIU Hao 写道:
> 在 2022-10-04 20:44, LIU Hao 写道:
>> Attached are revised patches. These are exported from trunk.
>>
> 
> Revised further. The patch for libgfortran has been committed to trunk today, so I include only the 
> other two.
> 
>    * In the second patch, a space character has been inserted after
>      `(int)` for clearness.
> 
>    * The macro controlling how to build GCC itself has been renamed to
>      `TARGET_USING_MCFGTHREAD` for consistency.
> 
>    * Checks against `TARGET_USING_MCFGTHREAD` have been updated in a
>      more friendly way.
> 
>    * When not using mcfgthread, NTDLL is no longer a default library.
>      Although all recent Windows versions are based on the NT kernel,
>      there could still be people who want to target 9x or CE; thus
>      NTDLL is only added when it is potentially necessary, for example
>      when linking against the static libgcc.
> 
> 

Attached is the (previous) third patch, with configure scripts regenerated.


-- 
Best regards,
LIU Hao


[-- Attachment #1.1.2: 0002-gcc-Add-mcf-thread-model-support-from-mcfgthread.patch --]
[-- Type: text/plain, Size: 12580 bytes --]

From c32690fa4878d8824a0e05e54f614a8dd9ed68b7 Mon Sep 17 00:00:00 2001
From: LIU Hao <lh_mouse@126.com>
Date: Sat, 16 Apr 2022 00:46:23 +0800
Subject: [PATCH 2/2] gcc: Add 'mcf' thread model support from mcfgthread

This patch adds the new thread model `mcf`, which implements mutexes
and condition variables with the mcfgthread library.

Source code for mcfgthread is available at <https://github.com/lhmouse/mcfgthread>.

config/ChangeLog:
	* gthr.m4 (GCC_AC_THREAD_HEADER): Add new case for `mcf` thread
	model

gcc/config/ChangeLog:
	* i386/mingw-mcfgthread.h: New file
	* i386/mingw32.h: Add builtin macro and default libraries for
	mcfgthread when thread model is `mcf`

gcc/ChangeLog:
	* config.gcc: Include 'i386/mingw-mcfgthread.h' when thread model
	is `mcf`
	* configure.ac: Recognize `mcf` as a valid thread model
	* configure: Regenerate

libatomic/ChangeLog:
	* configure.tgt: Add new case for `mcf` thread model

libgcc/ChangeLog:
	* config.host: Add new cases for `mcf` thread model
	* config/i386/gthr-mcf.h: New file
	* config/i386/t-mingw-mcfgthread: New file
	* config/i386/t-slibgcc-cygming: Add mcfgthread for libgcc DLL
	* configure: Regenerate

libstdc++-v3/ChangeLog:
	* libsupc++/atexit_thread.cc (__cxa_thread_atexit): Use
	implementation from mcfgthread if available
	* libsupc++/guard.cc (__cxa_guard_acquire, __cxa_guard_release,
	__cxa_guard_abort): Use implementations from mcfgthread if
	available
	* configure: Regenerate
---
 config/gthr.m4                          |  1 +
 gcc/config.gcc                          |  3 +++
 gcc/config/i386/mingw-mcfgthread.h      |  1 +
 gcc/config/i386/mingw32.h               | 13 ++++++++++-
 gcc/configure                           |  2 +-
 gcc/configure.ac                        |  2 +-
 libatomic/configure.tgt                 |  2 +-
 libgcc/config.host                      |  6 +++++
 libgcc/config/i386/gthr-mcf.h           |  1 +
 libgcc/config/i386/t-mingw-mcfgthread   |  1 +
 libgcc/config/i386/t-slibgcc-cygming    |  6 ++++-
 libgcc/configure                        |  1 +
 libstdc++-v3/configure                  | 13 ++++++-----
 libstdc++-v3/libsupc++/atexit_thread.cc | 20 ++++++++++++++++
 libstdc++-v3/libsupc++/guard.cc         | 31 +++++++++++++++++++++++++
 15 files changed, 92 insertions(+), 11 deletions(-)
 create mode 100644 gcc/config/i386/mingw-mcfgthread.h
 create mode 100644 libgcc/config/i386/gthr-mcf.h
 create mode 100644 libgcc/config/i386/t-mingw-mcfgthread

diff --git a/config/gthr.m4 b/config/gthr.m4
index 4b937306ad08..11996247f150 100644
--- a/config/gthr.m4
+++ b/config/gthr.m4
@@ -22,6 +22,7 @@ case $1 in
     tpf)	thread_header=config/s390/gthr-tpf.h ;;
     vxworks)	thread_header=config/gthr-vxworks.h ;;
     win32)	thread_header=config/i386/gthr-win32.h ;;
+    mcf)	thread_header=config/i386/gthr-mcf.h ;;
 esac
 AC_SUBST(thread_header)
 ])
diff --git a/gcc/config.gcc b/gcc/config.gcc
index eec544ff1bac..1f6adea1ab9b 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2091,6 +2091,9 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
 	if test x$enable_threads = xposix ; then
 		tm_file="${tm_file} i386/mingw-pthread.h"
 	fi
+	if test x$enable_threads = xmcf ; then
+		tm_file="${tm_file} i386/mingw-mcfgthread.h"
+	fi
 	tm_file="${tm_file} i386/mingw32.h"
 	# This makes the logic if mingw's or the w64 feature set has to be used
 	case ${target} in
diff --git a/gcc/config/i386/mingw-mcfgthread.h b/gcc/config/i386/mingw-mcfgthread.h
new file mode 100644
index 000000000000..7d4eda3ed494
--- /dev/null
+++ b/gcc/config/i386/mingw-mcfgthread.h
@@ -0,0 +1 @@
+#define TARGET_USING_MCFGTHREAD  1
diff --git a/gcc/config/i386/mingw32.h b/gcc/config/i386/mingw32.h
index d3ca0cd0279d..b5f31c3da0ac 100644
--- a/gcc/config/i386/mingw32.h
+++ b/gcc/config/i386/mingw32.h
@@ -32,6 +32,10 @@ along with GCC; see the file COPYING3.  If not see
 	 | MASK_STACK_PROBE | MASK_ALIGN_DOUBLE \
 	 | MASK_MS_BITFIELD_LAYOUT)
 
+#ifndef TARGET_USING_MCFGTHREAD
+#define TARGET_USING_MCFGTHREAD  0
+#endif
+
 /* See i386/crtdll.h for an alternative definition. _INTEGRAL_MAX_BITS
    is for compatibility with native compiler.  */
 #define EXTRA_OS_CPP_BUILTINS()					\
@@ -50,6 +54,8 @@ along with GCC; see the file COPYING3.  If not see
 	  builtin_define_std ("WIN64");				\
 	  builtin_define ("_WIN64");				\
 	}							\
+      if (TARGET_USING_MCFGTHREAD)				\
+	builtin_define ("__USING_MCFGTHREAD__");		\
     }								\
   while (0)
 
@@ -181,11 +187,16 @@ along with GCC; see the file COPYING3.  If not see
 #else
 #define SHARED_LIBGCC_SPEC " -lgcc "
 #endif
+#if TARGET_USING_MCFGTHREAD
+#define MCFGTHREAD_SPEC  " -lmcfgthread -lkernel32 -lntdll "
+#else
+#define MCFGTHREAD_SPEC  ""
+#endif
 #undef REAL_LIBGCC_SPEC
 #define REAL_LIBGCC_SPEC \
   "%{mthreads:-lmingwthrd} -lmingw32 \
    " SHARED_LIBGCC_SPEC " \
-   -lmoldname -lmingwex -lmsvcrt -lkernel32"
+   -lmoldname -lmingwex -lmsvcrt -lkernel32 " MCFGTHREAD_SPEC
 
 #undef STARTFILE_SPEC
 #define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
diff --git a/gcc/configure b/gcc/configure
index b512580414a6..421093f5868c 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -12900,7 +12900,7 @@ case ${enable_threads} in
     target_thread_file='single'
     ;;
   aix | dce | lynx | mipssde | posix | rtems | \
-  single | tpf | vxworks | win32)
+  single | tpf | vxworks | win32 | mcf)
     target_thread_file=${enable_threads}
     ;;
   *)
diff --git a/gcc/configure.ac b/gcc/configure.ac
index e48fcbfe18ea..e1ef2ecf0267 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1991,7 +1991,7 @@ case ${enable_threads} in
     target_thread_file='single'
     ;;
   aix | dce | lynx | mipssde | posix | rtems | \
-  single | tpf | vxworks | win32)
+  single | tpf | vxworks | win32 | mcf)
     target_thread_file=${enable_threads}
     ;;
   *)
diff --git a/libatomic/configure.tgt b/libatomic/configure.tgt
index 33f8c91ce771..86a59475b6e7 100644
--- a/libatomic/configure.tgt
+++ b/libatomic/configure.tgt
@@ -159,7 +159,7 @@ case "${target}" in
   *-*-mingw*)
 	# OS support for atomic primitives.
         case ${target_thread_file} in
-          win32)
+          win32 | mcf)
             config_path="${config_path} mingw"
             ;;
           posix)
diff --git a/libgcc/config.host b/libgcc/config.host
index 9dcc2538dc86..44a8218a31d3 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -825,6 +825,9 @@ i[34567]86-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
@@ -849,6 +852,9 @@ x86_64-*-mingw*)
 	  posix)
 	    tmake_file="i386/t-mingw-pthread $tmake_file"
 	    ;;
+	  mcf)
+	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
 	if test x$ac_cv_sjlj_exceptions = xyes; then
diff --git a/libgcc/config/i386/gthr-mcf.h b/libgcc/config/i386/gthr-mcf.h
new file mode 100644
index 000000000000..58131bb7ca92
--- /dev/null
+++ b/libgcc/config/i386/gthr-mcf.h
@@ -0,0 +1 @@
+#include <mcfgthread/gthr.h>
diff --git a/libgcc/config/i386/t-mingw-mcfgthread b/libgcc/config/i386/t-mingw-mcfgthread
new file mode 100644
index 000000000000..c5b817f09b71
--- /dev/null
+++ b/libgcc/config/i386/t-mingw-mcfgthread
@@ -0,0 +1 @@
+SHLIB_MCFGTHREAD_LIBS = -lmcfgthread -lkernel32 -lntdll
diff --git a/libgcc/config/i386/t-slibgcc-cygming b/libgcc/config/i386/t-slibgcc-cygming
index 6236c78e4668..6871498cf60e 100644
--- a/libgcc/config/i386/t-slibgcc-cygming
+++ b/libgcc/config/i386/t-slibgcc-cygming
@@ -27,6 +27,9 @@ endif
 ifndef SHLIB_PTHREAD_LDFLAG
 SHLIB_PTHREAD_LDFLAG =
 endif
+ifndef SHLIB_MCFGTHREAD_LIBS
+SHLIB_MCFGTHREAD_LIBS =
+endif
 
 SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
 	if [ ! -d $(SHLIB_DIR) ]; then \
@@ -37,7 +40,8 @@ SHLIB_LINK = $(LN_S) -f $(SHLIB_MAP) $(SHLIB_MAP).def && \
 	$(SHLIB_MAP).def \
 	-Wl,--out-implib,$(SHLIB_DIR)/$(SHLIB_IMPLIB).tmp \
 	-o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
-	$(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) && \
+	$(SHLIB_OBJS) ${SHLIB_PTHREAD_LDFLAG} $(SHLIB_LC) \
+	$(SHLIB_MCFGTHREAD_LIBS) && \
 	if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
 	  mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
 		$(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
diff --git a/libgcc/configure b/libgcc/configure
index 61f3ace2891c..be5d45f1755c 100755
--- a/libgcc/configure
+++ b/libgcc/configure
@@ -5699,6 +5699,7 @@ case $target_thread_file in
     tpf)	thread_header=config/s390/gthr-tpf.h ;;
     vxworks)	thread_header=config/gthr-vxworks.h ;;
     win32)	thread_header=config/i386/gthr-win32.h ;;
+    mcf)	thread_header=config/i386/gthr-mcf.h ;;
 esac
 
 
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 7ead77a5c800..08b0c4e7fcfd 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -15802,6 +15802,7 @@ case $target_thread_file in
     tpf)	thread_header=config/s390/gthr-tpf.h ;;
     vxworks)	thread_header=config/gthr-vxworks.h ;;
     win32)	thread_header=config/i386/gthr-win32.h ;;
+    mcf)	thread_header=config/i386/gthr-mcf.h ;;
 esac
 
 
@@ -16009,7 +16010,7 @@ $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
   # Fake what AC_TRY_COMPILE does.
 
     cat > conftest.$ac_ext << EOF
-#line 16012 "configure"
+#line 16013 "configure"
 int main()
 {
   typedef bool atomic_type;
@@ -16044,7 +16045,7 @@ $as_echo "$glibcxx_cv_atomic_bool" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 16047 "configure"
+#line 16048 "configure"
 int main()
 {
   typedef short atomic_type;
@@ -16079,7 +16080,7 @@ $as_echo "$glibcxx_cv_atomic_short" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 16082 "configure"
+#line 16083 "configure"
 int main()
 {
   // NB: _Atomic_word not necessarily int.
@@ -16115,7 +16116,7 @@ $as_echo "$glibcxx_cv_atomic_int" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 16118 "configure"
+#line 16119 "configure"
 int main()
 {
   typedef long long atomic_type;
@@ -16271,7 +16272,7 @@ $as_echo "mutex" >&6; }
   # unnecessary for this test.
 
     cat > conftest.$ac_ext << EOF
-#line 16274 "configure"
+#line 16275 "configure"
 int main()
 {
   _Decimal32 d1;
@@ -16313,7 +16314,7 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
   # unnecessary for this test.
 
   cat > conftest.$ac_ext << EOF
-#line 16316 "configure"
+#line 16317 "configure"
 template<typename T1, typename T2>
   struct same
   { typedef T2 type; };
diff --git a/libstdc++-v3/libsupc++/atexit_thread.cc b/libstdc++-v3/libsupc++/atexit_thread.cc
index a2693d0424e1..2f936ab02ce2 100644
--- a/libstdc++-v3/libsupc++/atexit_thread.cc
+++ b/libstdc++-v3/libsupc++/atexit_thread.cc
@@ -25,6 +25,24 @@
 #include <cstdlib>
 #include <new>
 #include "bits/gthr.h"
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
+		     void *obj, void *dso_handle) _GLIBCXX_NOTHROW
+{
+  return __MCF_cxa_thread_atexit (dtor, obj, dso_handle);
+}
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #ifdef _GLIBCXX_THREAD_ATEXIT_WIN32
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h>
@@ -173,3 +191,5 @@ __cxxabiv1::__cxa_thread_atexit (void (_GLIBCXX_CDTOR_CALLABI *dtor)(void *),
 }
 
 #endif /* _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */
+
+#endif // __USING_MCFGTHREAD__
diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc
index abb57117cdfd..0f81a22c6845 100644
--- a/libstdc++-v3/libsupc++/guard.cc
+++ b/libstdc++-v3/libsupc++/guard.cc
@@ -28,6 +28,35 @@
 #include <cxxabi.h>
 #include <exception>
 #include <new>
+
+#ifdef __USING_MCFGTHREAD__
+
+#include <mcfgthread/cxa.h>
+
+namespace __cxxabiv1 {
+
+extern "C" int
+__cxa_guard_acquire (__guard* g) _GLIBCXX_NOTHROW
+  {
+    return __MCF_cxa_guard_acquire(g);
+  }
+
+extern "C" void
+__cxa_guard_release (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_release(g);
+  }
+
+extern "C" void
+__cxa_guard_abort (__guard* g) _GLIBCXX_NOTHROW
+  {
+    __MCF_cxa_guard_abort(g);
+  }
+
+}  // namespace __cxxabiv1
+
+#else // __USING_MCFGTHREAD__
+
 #include <ext/atomicity.h>
 #include <ext/concurrence.h>
 #include <bits/atomic_lockfree_defines.h>
@@ -458,3 +487,5 @@ namespace __cxxabiv1
 #endif
   }
 }
+
+#endif // __USING_MCFGTHREAD__
-- 
2.37.3


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-11 13:22           ` LIU Hao
@ 2022-10-14  9:39             ` Jonathan Yong
  2022-10-19 13:55               ` Jonathan Yong
  0 siblings, 1 reply; 58+ messages in thread
From: Jonathan Yong @ 2022-10-14  9:39 UTC (permalink / raw)
  To: LIU Hao, gcc-patches

On 10/11/22 13:22, LIU Hao wrote:
> 在 2022-10-10 23:56, LIU Hao 写道:
>> 在 2022-10-04 20:44, LIU Hao 写道:
>>> Attached are revised patches. These are exported from trunk.
>>>
>>
>> Revised further. The patch for libgfortran has been committed to trunk 
>> today, so I include only the other two.
>>
>>    * In the second patch, a space character has been inserted after
>>      `(int)` for clearness.
>>
>>    * The macro controlling how to build GCC itself has been renamed to
>>      `TARGET_USING_MCFGTHREAD` for consistency.
>>
>>    * Checks against `TARGET_USING_MCFGTHREAD` have been updated in a
>>      more friendly way.
>>
>>    * When not using mcfgthread, NTDLL is no longer a default library.
>>      Although all recent Windows versions are based on the NT kernel,
>>      there could still be people who want to target 9x or CE; thus
>>      NTDLL is only added when it is potentially necessary, for example
>>      when linking against the static libgcc.
>>
>>
> 
> Attached is the (previous) third patch, with configure scripts regenerated.
> 
> 

Any more comments?

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-14  9:39             ` Jonathan Yong
@ 2022-10-19 13:55               ` Jonathan Yong
  2022-10-19 19:53                 ` Bernhard Reutner-Fischer
  0 siblings, 1 reply; 58+ messages in thread
From: Jonathan Yong @ 2022-10-19 13:55 UTC (permalink / raw)
  To: LIU Hao, gcc-patches

On 10/14/22 09:39, Jonathan Yong wrote:
> On 10/11/22 13:22, LIU Hao wrote:
>> 在 2022-10-10 23:56, LIU Hao 写道:
>>> 在 2022-10-04 20:44, LIU Hao 写道:
>>>> Attached are revised patches. These are exported from trunk.
>>>>
>>>
>>> Revised further. The patch for libgfortran has been committed to 
>>> trunk today, so I include only the other two.
>>>
>>>    * In the second patch, a space character has been inserted after
>>>      `(int)` for clearness.
>>>
>>>    * The macro controlling how to build GCC itself has been renamed to
>>>      `TARGET_USING_MCFGTHREAD` for consistency.
>>>
>>>    * Checks against `TARGET_USING_MCFGTHREAD` have been updated in a
>>>      more friendly way.
>>>
>>>    * When not using mcfgthread, NTDLL is no longer a default library.
>>>      Although all recent Windows versions are based on the NT kernel,
>>>      there could still be people who want to target 9x or CE; thus
>>>      NTDLL is only added when it is potentially necessary, for example
>>>      when linking against the static libgcc.
>>>
>>>
>>
>> Attached is the (previous) third patch, with configure scripts 
>> regenerated.
>>
>>
> 
> Any more comments?

Just pushed to master branch.


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-19 13:55               ` Jonathan Yong
@ 2022-10-19 19:53                 ` Bernhard Reutner-Fischer
  2022-10-20  1:25                   ` LIU Hao
  0 siblings, 1 reply; 58+ messages in thread
From: Bernhard Reutner-Fischer @ 2022-10-19 19:53 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: LIU Hao, GCC Patches, Bernhard Reutner-Fischer

On Wed, 19 Oct 2022 at 15:56, Jonathan Yong via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:

> Just pushed to master branch.

Wouldn't you want to cut down on the libs respectively refine the
order of the libs, though?
You've now got:
+#define MCFGTHREAD_SPEC  " -lmcfgthread -lkernel32 -lntdll "
+#else
+#define MCFGTHREAD_SPEC  ""
+#endif
 #undef REAL_LIBGCC_SPEC
 #define REAL_LIBGCC_SPEC \
   "%{mthreads:-lmingwthrd} -lmingw32 \
    " SHARED_LIBGCC_SPEC " \
-   -lmoldname -lmingwex -lmsvcrt -lkernel32"
+   -lmoldname -lmingwex -lmsvcrt -lkernel32 " MCFGTHREAD_SPEC

which has kernel32 twice, which might not be ideal for the speed of linking?
I'm not familiar with the content of ntdll so cannot judge if you'd put that in
MCFGTHREAD_SPEC and drop kernel32 there, though, and put the whole
MCFG spec simply before the kernel32 in the REAL_LIBGCC_SPEC.

i.e.
+#define MCFGTHREAD_SPEC  " -lmcfgthread -lntdll "
...
+   -lmoldname -lmingwex -lmsvcrt " MCFGTHREAD_SPEC " -lkernel32 "

I hope this is constructive.
thanks,

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-19 19:53                 ` Bernhard Reutner-Fischer
@ 2022-10-20  1:25                   ` LIU Hao
  0 siblings, 0 replies; 58+ messages in thread
From: LIU Hao @ 2022-10-20  1:25 UTC (permalink / raw)
  To: Bernhard Reutner-Fischer, Jonathan Yong; +Cc: GCC Patches


[-- Attachment #1.1: Type: text/plain, Size: 1465 bytes --]

在 2022/10/20 03:53, Bernhard Reutner-Fischer 写道:
> 
> which has kernel32 twice, which might not be ideal for the speed of linking?
> I'm not familiar with the content of ntdll so cannot judge if you'd put that in
> MCFGTHREAD_SPEC and drop kernel32 there, though, and put the whole
> MCFG spec simply before the kernel32 in the REAL_LIBGCC_SPEC.
> 
> i.e.
> +#define MCFGTHREAD_SPEC  " -lmcfgthread -lntdll "
> ...
> +   -lmoldname -lmingwex -lmsvcrt " MCFGTHREAD_SPEC " -lkernel32 "
> 
> I hope this is constructive.
> thanks,

NTDLL is the user-mode syscall library i.e. it mainly provides syscalls as functions.

Putting `-lmcfgthread` before `-lkernel32` was what I did in the beginning. However, I had an 
impression that NTDLL and KERNEL32 may both export some functions (I believe this is no longer the 
case now). Since MSVCRT in mingw-w64 is not a 'pure' import library and contains some functions that 
we implement on top of KERNEL32, the ideal solution would be

    ```
    #define MCFGTHREAD_SPEC  " -lmcfgthread "
    #define MCFGTHREAD_NTDLL_SPEC  " -lntdll "
      ...
    -lmsvcrt " MCFGTHREAD_SPEC " -lkernel32 " MCFGTHREAD_NTDLL_SPEC
    ```

(NTDLL is only necessary when linking against the shared library.)

The committed patch inserted MCFGTHREAD after KERNEL32 for simplicity, but if you do think we had 
better not repeat KERNEL32 twice, I can propose another patch.


-- 
Best regards,
LIU Hao

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-01 18:34 Adding a new thread model to GCC LIU Hao
  2022-10-01 20:02 ` Bernhard Reutner-Fischer
@ 2022-10-21  9:58 ` Jonathan Wakely
  2022-10-21 10:09   ` i.nixman
  2022-10-21 11:44   ` Eric Botcazou
  1 sibling, 2 replies; 58+ messages in thread
From: Jonathan Wakely @ 2022-10-21  9:58 UTC (permalink / raw)
  To: LIU Hao; +Cc: gcc-patches, libstdc++, Eric Botcazou

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.

On Sat, 1 Oct 2022 at 19:35, LIU Hao via Libstdc++
<libstdc++@gcc.gnu.org> 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


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21  9:58 ` Jonathan Wakely
@ 2022-10-21 10:09   ` i.nixman
  2022-10-21 10:48     ` Jonathan Wakely
  2022-10-21 11:36     ` LIU Hao
  2022-10-21 11:44   ` Eric Botcazou
  1 sibling, 2 replies; 58+ messages in thread
From: i.nixman @ 2022-10-21 10:09 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: LIU Hao, libstdc++, gcc-patches, Eric Botcazou

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++
> <libstdc++@gcc.gnu.org> 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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 10:09   ` i.nixman
@ 2022-10-21 10:48     ` Jonathan Wakely
  2022-10-21 10:55       ` i.nixman
  2022-10-21 11:36     ` LIU Hao
  1 sibling, 1 reply; 58+ messages in thread
From: Jonathan Wakely @ 2022-10-21 10:48 UTC (permalink / raw)
  To: i.nixman; +Cc: LIU Hao, libstdc++, gcc-patches, Eric Botcazou

On Fri, 21 Oct 2022 at 11:10, i.nixman--- via Libstdc++
<libstdc++@gcc.gnu.org> 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).

The benefits of using the native thread model for the OS seems
obvious. The question is which patch to do that should we use.


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 10:48     ` Jonathan Wakely
@ 2022-10-21 10:55       ` i.nixman
  0 siblings, 0 replies; 58+ messages in thread
From: i.nixman @ 2022-10-21 10:55 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: LIU Hao, libstdc++, gcc-patches, Eric Botcazou

On 2022-10-21 10:48, Jonathan Wakely wrote:
> On Fri, 21 Oct 2022 at 11:10, i.nixman--- via Libstdc++
> <libstdc++@gcc.gnu.org> 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 10:09   ` i.nixman
  2022-10-21 10:48     ` Jonathan Wakely
@ 2022-10-21 11:36     ` LIU Hao
  2022-10-21 11:54       ` i.nixman
  2022-10-21 12:13       ` Jacek Caban
  1 sibling, 2 replies; 58+ messages in thread
From: LIU Hao @ 2022-10-21 11:36 UTC (permalink / raw)
  To: i.nixman, Jonathan Wakely; +Cc: libstdc++, gcc-patches, Eric Botcazou


[-- Attachment #1.1: Type: text/plain, Size: 3867 bytes --]

在 2022/10/21 18:09, i.nixman@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.


[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

-- 
Best regards,
LIU Hao

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21  9:58 ` Jonathan Wakely
  2022-10-21 10:09   ` i.nixman
@ 2022-10-21 11:44   ` Eric Botcazou
  2022-10-21 11:55     ` i.nixman
  2022-10-24  6:53     ` i.nixman
  1 sibling, 2 replies; 58+ messages in thread
From: Eric Botcazou @ 2022-10-21 11:44 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: LIU Hao, libstdc++, gcc-patches

> 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.

-- 
Eric Botcazou



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 11:36     ` LIU Hao
@ 2022-10-21 11:54       ` i.nixman
  2022-10-21 12:19         ` LIU Hao
  2022-10-21 12:13       ` Jacek Caban
  1 sibling, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-10-21 11:54 UTC (permalink / raw)
  To: LIU Hao; +Cc: Jonathan Wakely, libstdc++, gcc-patches, Eric Botcazou

On 2022-10-21 11:36, LIU Hao wrote:
> 在 2022/10/21 18:09, i.nixman@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

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 11:44   ` Eric Botcazou
@ 2022-10-21 11:55     ` i.nixman
  2022-10-21 12:30       ` Jacek Caban
  2022-10-24  6:53     ` i.nixman
  1 sibling, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-10-21 11:55 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Jonathan Wakely, LIU Hao, libstdc++, 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 11:36     ` LIU Hao
  2022-10-21 11:54       ` i.nixman
@ 2022-10-21 12:13       ` Jacek Caban
  2022-10-21 12:29         ` LIU Hao
  1 sibling, 1 reply; 58+ messages in thread
From: Jacek Caban @ 2022-10-21 12:13 UTC (permalink / raw)
  To: lh_mouse, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 778 bytes --]

> 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.

This is not true for past 15 years, CRITICAL_SECTIONS use something like RtlWaitOnAddress (an equivalent of futexes) since Vista, see Wine implementation for details:
https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/sync.c#L190

Jacek

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 11:54       ` i.nixman
@ 2022-10-21 12:19         ` LIU Hao
  2022-10-21 12:34           ` i.nixman
  0 siblings, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-21 12:19 UTC (permalink / raw)
  To: i.nixman; +Cc: Jonathan Wakely, libstdc++, gcc-patches, Eric Botcazou


[-- Attachment #1.1: Type: text/plain, Size: 1833 bytes --]

在 2022/10/21 19:54, i.nixman@autistici.org 写道:
> 
> 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 ...)
> 

While it is possible to rebuild winpthreads from scratch, I don't think it's worth:

   * There are many POSIX facilities that we don't support: rwlock,
     cancellation, signals, etc.

   * GCC can choose to implement `std::thread` etc. on C11 <threads.h>,
     which libcxx already has, but I haven't tested it.
     (mcfgthread also has a C11 header, but not one for libcxx.)


> 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 =))
> 

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.

   * 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.


-- 
Best regards,
LIU Hao

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 12:13       ` Jacek Caban
@ 2022-10-21 12:29         ` LIU Hao
  2022-10-21 12:40           ` Jacek Caban
  0 siblings, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-21 12:29 UTC (permalink / raw)
  To: Jacek Caban, GCC Patches


[-- Attachment #1.1: Type: text/plain, Size: 751 bytes --]

在 2022/10/21 20:13, Jacek Caban 写道:
> 
> This is not true for past 15 years, CRITICAL_SECTIONS use something like RtlWaitOnAddress (an equivalent of futexes) since Vista, see Wine implementation for details:
> https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/sync.c#L190
> 
> 

Ah Jacek, nice to see you here.

I haven't dug into this too much, though. From my limited knowledge (mostly from reading 
disassembly) now CRITICAL_SECTION uses `NtWaitForAlertByThreadId` (and no longer keyed events or 
semaphores). As with `WaitOnAddress()`, there seems to be some global data structure, protected by a 
spin lock. It's just another undocumented syscall. Keyed events are still functional.


-- 
Best regards,
LIU Hao

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 11:55     ` i.nixman
@ 2022-10-21 12:30       ` Jacek Caban
  2022-10-23  0:36         ` NightStrike
  0 siblings, 1 reply; 58+ messages in thread
From: Jacek Caban @ 2022-10-21 12:30 UTC (permalink / raw)
  To: i.nixman, 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!

I agree as well and I expressed that on mingw-w64 ML when the patch was introduced [1]. My main concern with the new threading model is that instead of solving root of the problem, it introduces more fragmentation with no clear benefit.

On top of that, mcfgthread library is way more invasive than it needs to be. It requires maintaining per-thread struct and reimplements a number of things instead of leveraging OS capabilities. Author also plans to make invasive changes to mingw-w64-crt, which go against it current approach of being agnostic to threading model.

Jacek

[1] https://sourceforge.net/p/mingw-w64/mailman/message/37719727/


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 12:19         ` LIU Hao
@ 2022-10-21 12:34           ` i.nixman
  2022-10-24  3:40             ` LIU Hao
  0 siblings, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-10-21 12:34 UTC (permalink / raw)
  To: LIU Hao; +Cc: Wakely, libstdc++, gcc-patches, Eric Botcazou

On 2022-10-21 12:19, LIU Hao wrote:
> 在 2022/10/21 19:54, i.nixman@autistici.org 写道:

<skip>

> 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 12:29         ` LIU Hao
@ 2022-10-21 12:40           ` Jacek Caban
  0 siblings, 0 replies; 58+ messages in thread
From: Jacek Caban @ 2022-10-21 12:40 UTC (permalink / raw)
  To: LIU Hao, GCC Patches

On 10/21/22 14:29, LIU Hao wrote:
> 在 2022/10/21 20:13, Jacek Caban 写道:
>>
>> This is not true for past 15 years, CRITICAL_SECTIONS use something 
>> like RtlWaitOnAddress (an equivalent of futexes) since Vista, see 
>> Wine implementation for details:
>> https://gitlab.winehq.org/wine/wine/-/blob/master/dlls/ntdll/sync.c#L190
>>
>>
>
> Ah Jacek, nice to see you here.
>
> I haven't dug into this too much, though. From my limited knowledge 
> (mostly from reading disassembly) now CRITICAL_SECTION uses 
> `NtWaitForAlertByThreadId` (and no longer keyed events or semaphores). 
> As with `WaitOnAddress()`, there seems to be some global data 
> structure, protected by a spin lock. It's just another undocumented 
> syscall. Keyed events are still functional.


NtWaitForAlertByThreadId() is an underlying syscall that's used by 
WaitOnAddress(). Anyway, you don't need to worry about that if you just 
use public CRITICAL_SECTION APIs.


Jacek


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 12:30       ` Jacek Caban
@ 2022-10-23  0:36         ` NightStrike
  0 siblings, 0 replies; 58+ messages in thread
From: NightStrike @ 2022-10-23  0:36 UTC (permalink / raw)
  To: Jacek Caban; +Cc: i.nixman, GCC Patches

On Fri, Oct 21, 2022 at 8:33 AM Jacek Caban via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> 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!
>
> I agree as well and I expressed that on mingw-w64 ML when the patch was introduced [1]. My main concern with the new threading model is that instead of solving root of the problem, it introduces more fragmentation with no clear benefit.
>
> On top of that, mcfgthread library is way more invasive than it needs to be. It requires maintaining per-thread struct and reimplements a number of things instead of leveraging OS capabilities. Author also plans to make invasive changes to mingw-w64-crt, which go against it current approach of being agnostic to threading model.
>
> Jacek
>
> [1] https://sourceforge.net/p/mingw-w64/mailman/message/37719727/

FWIW, Eric's proposal makes more practical sense.  Right now, people
ship many permutations of the compiler:
x86, x64, x86+x64
dw2, sjlj (rarely), seh
win32, posix+winpthread

This is not sustainable, and certain combinations are largely
incompatible (which makes for instance providing a windows release of
MySpecialLibrary.dll confusing).  We used to have a matrix of
combinations on the website, but I see that that's no longer present.
In any case, it took a long time for sjlj to fall out of vogue (maybe
old habits die hard?).  That implies, to me, that winpthreads
similarly won't be deprecated, it'll just be yet another set of
archives to download and confuse people with.

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 12:34           ` i.nixman
@ 2022-10-24  3:40             ` LIU Hao
  2022-10-24 20:50               ` Jacek Caban
  0 siblings, 1 reply; 58+ messages in thread
From: LIU Hao @ 2022-10-24  3:40 UTC (permalink / raw)
  To: i.nixman; +Cc: Wakely, libstdc++, gcc-patches, Eric Botcazou


[-- Attachment #1.1: Type: text/plain, Size: 4199 bytes --]

在 2022/10/21 20:34, i.nixman@autistici.org 写道:
> 
> got it...
> anyway it seems logical to me the way I proposed :)
> 
> 

Below is a message forwarded from mingw-w64-public, elaborating the necessity of a new thread model.

As there are objections from other mingw-w64 developers, I am putting those patches against 
mingw-w64-crt on hold for now. Despite that, all threading facilities - mutexes, condition 
variables, once flags, etc. - are still fully functional within the mcf thread model.

In addition, I will keep maintaining my personal builds (from GCC 12 release branch) with these 
patches at https://gcc-mcf.lhmouse.com/.


-------- Forwarded Message --------
在 2022/10/23 18:06, Jacek Caban 写道:
 >
 > Please, let's not do that. It's possible to fix existing implementations, we don't need to make
 > things more complicated than they are.
 >

Okay okay, I think I have to compose a thorough list of problems that we are facing at the moment, 
and had better have a permalink to the mailing list archive that I can reference elsewhere. I have 
been tired of repeating the same grounds of arguments again and again:


1. In a DLL, destructors of static objects and callbacks that are registered
     with `atexit()`, are executed by `LdrShutdownProcess()`, after all the other
     thread have been terminated `ZwTerminateProcessO(NULL, status)`. This means
     that, if another thread has been terminated while holding a mutex, the mutex
     can never get unlocked. If a destructor attempts to lock the same mutex,
     deadlocks will occur. Destructors of executables do not suffer from this
     issue, because they are executed before `RtlExitUserProcess()`.

     Standard behavior: Static destructors and exit callbacks should be executed
     while other threads are running. If another thread attempts to access a
     destroyed object, the behavior is undefined; the user is responsible to
     prevent this from happening, by joining or suspending it.


2. Following 1, in a DLL, static destructors and exit callbacks are still
     invoked when `_Exit()` or `quick_exit()` is called.

     Standard behavior: `_Exit()` should not perform any cleanup; not even open
     files are flushed. `quick_exit()` shall invoke all quick-exit callbacks in
     reverse order, then call `_Exit()`.


3. There is a use-after-free bug [1] about thread-local destructors. I suspect
     this is caused by emutls, because GCC uses `__cxa_thread_atexit()` to
     register thread-local destructors, which could interleave with
     `emutls_destroy()`.

     Standard behavior: This is not allowed to happen. mcfgthread solves this
     issue by running thread-local destructors and thread-specific key
     destructors as two separate passes [3].

     [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80816
     [2] 
https://github.com/gcc-mirror/gcc/blob/f84e4fb44aa26b71fbc64e0532fd24d96e5caa3f/libgcc/emutls.c#L96
     [3] 
https://github.com/lhmouse/mcfgthread/blob/63e034d375caf585e2921cd3455f1048feb2172d/src/xglobals.c#L249


4. In the win32 thread model, thread-specific key destructors are called at
     process exit [4], after static destructors.

     Standard behavior: They shall be called only when a thread exits, and the
     associated thread-specific values are not a null pointer. They shall not be
     called when a program terminates; instead, users are responsible for
     deallocating such resources before calling `exit()`. This requirement is
     missing in POSIX, but formally specified by ISO/IEC 9899:2017, as the 4th
     paragraph in '7.26.6.1 The tss_create function'.

     [4] 
https://github.com/mingw-w64/mingw-w64/blob/d0a034a04d312434b842c4869a8a900568d8db98/mingw-w64-crt/crt/tlsthrd.c#L134


5. Wait operations, of timed mutexes and condition variables, should take
     absolute time points as `struct timespec`.

     Standard behavior: Both POSIX and ISO C specifies them as such, while all
     Windows APIs take relative durations as a 32-bit integer of milliseconds,
     which can also easily get overflown.


-- 
Best regards,
LIU Hao

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-21 11:44   ` Eric Botcazou
  2022-10-21 11:55     ` i.nixman
@ 2022-10-24  6:53     ` i.nixman
  2022-10-24  8:15       ` Eric Botcazou
  2022-10-31  9:18       ` Eric Botcazou
  1 sibling, 2 replies; 58+ messages in thread
From: i.nixman @ 2022-10-24  6:53 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: libstdc++, 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-24  6:53     ` i.nixman
@ 2022-10-24  8:15       ` Eric Botcazou
  2022-10-24  8:20         ` i.nixman
  2022-10-31  9:18       ` Eric Botcazou
  1 sibling, 1 reply; 58+ messages in thread
From: Eric Botcazou @ 2022-10-24  8:15 UTC (permalink / raw)
  To: i.nixman; +Cc: libstdc++, gcc-patches

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

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.

-- 
Eric Botcazou



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-24  8:15       ` Eric Botcazou
@ 2022-10-24  8:20         ` i.nixman
  0 siblings, 0 replies; 58+ messages in thread
From: i.nixman @ 2022-10-24  8:20 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: libstdc++, 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-24  3:40             ` LIU Hao
@ 2022-10-24 20:50               ` Jacek Caban
  0 siblings, 0 replies; 58+ messages in thread
From: Jacek Caban @ 2022-10-24 20:50 UTC (permalink / raw)
  To: LIU Hao, i.nixman, mingw-w64-public
  Cc: Wakely, libstdc++, gcc-patches, Eric Botcazou

On 10/24/22 05:40, LIU Hao via Gcc-patches wrote:
> 在 2022/10/21 20:34, i.nixman@autistici.org 写道:
>>
>> got it...
>> anyway it seems logical to me the way I proposed :)
>>
>>
>
> Below is a message forwarded from mingw-w64-public, elaborating the 
> necessity of a new thread model.
>
> As there are objections from other mingw-w64 developers, I am putting 
> those patches against mingw-w64-crt on hold for now. Despite that, all 
> threading facilities - mutexes, condition variables, once flags, etc. 
> - are still fully functional within the mcf thread model.
>
> In addition, I will keep maintaining my personal builds (from GCC 12 
> release branch) with these patches at https://gcc-mcf.lhmouse.com/.
>
>
> -------- Forwarded Message --------
> 在 2022/10/23 18:06, Jacek Caban 写道:
> >
> > Please, let's not do that. It's possible to fix existing 
> implementations, we don't need to make
> > things more complicated than they are.
> >
>
> Okay okay, I think I have to compose a thorough list of problems that 
> we are facing at the moment, and had better have a permalink to the 
> mailing list archive that I can reference elsewhere. I have been tired 
> of repeating the same grounds of arguments again and again:
>
>
> 1. In a DLL, destructors of static objects and callbacks that are 
> registered
>     with `atexit()`, are executed by `LdrShutdownProcess()`, after all 
> the other
>     thread have been terminated `ZwTerminateProcessO(NULL, status)`. 
> This means
>     that, if another thread has been terminated while holding a mutex, 
> the mutex
>     can never get unlocked. If a destructor attempts to lock the same 
> mutex,
>     deadlocks will occur. Destructors of executables do not suffer 
> from this
>     issue, because they are executed before `RtlExitUserProcess()`.
>
>     Standard behavior: Static destructors and exit callbacks should be 
> executed
>     while other threads are running. If another thread attempts to 
> access a
>     destroyed object, the behavior is undefined; the user is 
> responsible to
>     prevent this from happening, by joining or suspending it.
>
>
> 2. Following 1, in a DLL, static destructors and exit callbacks are still
>     invoked when `_Exit()` or `quick_exit()` is called.
>
>     Standard behavior: `_Exit()` should not perform any cleanup; not 
> even open
>     files are flushed. `quick_exit()` shall invoke all quick-exit 
> callbacks in
>     reverse order, then call `_Exit()`.
>
>
> 3. There is a use-after-free bug [1] about thread-local destructors. I 
> suspect
>     this is caused by emutls, because GCC uses `__cxa_thread_atexit()` to
>     register thread-local destructors, which could interleave with
>     `emutls_destroy()`.
>
>     Standard behavior: This is not allowed to happen. mcfgthread 
> solves this
>     issue by running thread-local destructors and thread-specific key
>     destructors as two separate passes [3].
>
>     [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80816
>     [2] 
> https://github.com/gcc-mirror/gcc/blob/f84e4fb44aa26b71fbc64e0532fd24d96e5caa3f/libgcc/emutls.c#L96
>     [3] 
> https://github.com/lhmouse/mcfgthread/blob/63e034d375caf585e2921cd3455f1048feb2172d/src/xglobals.c#L249
>
>
> 4. In the win32 thread model, thread-specific key destructors are 
> called at
>     process exit [4], after static destructors.
>
>     Standard behavior: They shall be called only when a thread exits, 
> and the
>     associated thread-specific values are not a null pointer. They 
> shall not be
>     called when a program terminates; instead, users are responsible for
>     deallocating such resources before calling `exit()`. This 
> requirement is
>     missing in POSIX, but formally specified by ISO/IEC 9899:2017, as 
> the 4th
>     paragraph in '7.26.6.1 The tss_create function'.
>
>     [4] 
> https://github.com/mingw-w64/mingw-w64/blob/d0a034a04d312434b842c4869a8a900568d8db98/mingw-w64-crt/crt/tlsthrd.c#L134


Those 4 points describes problems that you solve in the new threading 
model, but there is no reason they can't be fixed for existing threading 
models. In fact, ideally they would be fixed for all threading models. 
Except now we need to worry about one more threading model, meaning that 
future bugs will be even harder to fix.


>
> 5. Wait operations, of timed mutexes and condition variables, should take
>     absolute time points as `struct timespec`.
>
>     Standard behavior: Both POSIX and ISO C specifies them as such, 
> while all
>     Windows APIs take relative durations as a 32-bit integer of 
> milliseconds,
>     which can also easily get overflown.


This also may be supported in existing threading models. Overflow is 
trivial to fix by waiting in a loop. (There are other reasons why OS 
support for absolute timeout is slightly better, but the price of this 
design decision makes it questionable. I plan to elaborate more on that 
on mingw ML, but I need to find time to do a bit of research first).


Jacek


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-24  6:53     ` i.nixman
  2022-10-24  8:15       ` Eric Botcazou
@ 2022-10-31  9:18       ` Eric Botcazou
  2022-10-31 15:22         ` i.nixman
                           ` (2 more replies)
  1 sibling, 3 replies; 58+ messages in thread
From: Eric Botcazou @ 2022-10-31  9:18 UTC (permalink / raw)
  To: i.nixman; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 6781 bytes --]

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

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  <ebotcazou@adacore.com>

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.
	(__gthread_key_delete): Minor tweak.
	(__gthread_getspecific): Likewise.
	(__gthread_setspecific): Likewise.
	(__gthread_mutex_init_function): Reimplement.
	(__gthread_mutex_destroy): Likewise.
	(__gthread_mutex_lock): Likewise.
	(__gthread_mutex_trylock): Likewise.
	(__gthread_mutex_unlock): Likewise.
	(__gthr_win32_abs_to_rel_time): Declare.
	(__gthread_recursive_mutex_init_function): Reimplement.
	(__gthread_recursive_mutex_destroy): Likewise.
	(__gthread_recursive_mutex_lock): Likewise.
	(__gthread_recursive_mutex_trylock): Likewise.
	(__gthread_recursive_mutex_unlock): Likewise.
	(__gthread_cond_destroy): New inline function.
	(__gthread_cond_wait_recursive): Likewise.
	* config/i386/gthr-win32.c: Delete everything.
	Include gthr-win32.h to get the out-of-line version of inline routines.
	Add compile-time checks for the local version of the Win32 types.
	* config/i386/gthr-win32-cond.c: New file.
	* config/i386/gthr-win32-thread.c: Likewise.
	* config/i386/t-gthr-win32: Add config/i386/gthr-win32-thread.c to the
	EH part, config/i386/gthr-win32-cond.c and config/i386/gthr-win32.c to
	the static version of libgcc.
	* config/i386/t-slibgcc-mingw: New file.
	* config/i386/libgcc-mingw.ver: Likewise.
libstdc++-v3/
	* acinclude.m4 (GLIBCXX_EXPORT_FLAGS): Substitute CPPFLAGS.
	(GLIBCXX_ENABLE_LIBSTDCXX_TIME): Set ac_has_sched_yield and
	ac_has_win32_sleep to yes for MinGW.  Change HAVE_WIN32_SLEEP
	into _GLIBCXX_USE_WIN32_SLEEP.
	(GLIBCXX_CHECK_GTHREADS): Add _WIN32_THREADS to compilation flags for
	Win32 threads and force _GTHREAD_USE_MUTEX_TIMEDLOCK to 0 for them.
	Add -D_WIN32_WINNT=0x0600 to compilation flags if yes was configured
	and add it to CPPFLAGS on success.
	* config.h.in: Regenerate.
	* configure: Likewise.
	* config/os/mingw32-w64/os_defines.h (_GLIBCXX_USE_GET_NPROCS_WIN32):
	Define to 1.
	* config/os/mingw32/os_defines.h (_GLIBCXX_USE_GET_NPROCS_WIN32): Ditto
	* src/c++11/thread.cc (get_nprocs): Provide Win32 implementation if
	_GLIBCXX_USE_GET_NPROCS_WIN32 is defined.  Replace HAVE_WIN32_SLEEP
	with USE_WIN32_SLEEP.
	* testsuite/19_diagnostics/headers/system_error/errc_std_c++0x.cc: Add
	missing conditional compilation.
	* testsuite/lib/libstdc++.exp (check_v3_target_sleep): Add support for
	_GLIBCXX_USE_WIN32_SLEEP.
	(check_v3_target_nprocs): Likewise for _GLIBCXX_USE_GET_NPROCS_WIN32.

-- 
Eric Botcazou

[-- Attachment #2: p13.diff --]
[-- Type: text/x-patch, Size: 54753 bytes --]

diff --git a/libgcc/config.host b/libgcc/config.host
index eb23abe89f5..d2087654c40 100644
--- a/libgcc/config.host
+++ b/libgcc/config.host
@@ -820,13 +820,13 @@ i[34567]86-*-mingw*)
 	fi
 	case ${target_thread_file} in
 	  win32)
-	    tmake_file="$tmake_file i386/t-gthr-win32"
+	    tmake_thr_file="i386/t-gthr-win32"
 	    ;;
 	  posix)
-	    tmake_file="i386/t-mingw-pthread $tmake_file"
+	    tmake_thr_file="i386/t-mingw-pthread"
 	    ;;
 	  mcf)
-	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    tmake_thr_file="i386/t-mingw-mcfgthread"
 	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
@@ -842,18 +842,18 @@ i[34567]86-*-mingw*)
 	else
 		tmake_dlldir_file="i386/t-dlldir-x"
 	fi
-	tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_dlldir_file} i386/t-slibgcc-cygming i386/t-cygming i386/t-mingw32 t-crtfm i386/t-chkstk t-dfprules"
+	tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_thr_file} ${tmake_dlldir_file} i386/t-slibgcc-cygming i386/t-slibgcc-mingw i386/t-cygming i386/t-mingw32 t-crtfm i386/t-chkstk t-dfprules"
 	;;
 x86_64-*-mingw*)
 	case ${target_thread_file} in
 	  win32)
-	    tmake_file="$tmake_file i386/t-gthr-win32"
+	    tmake_thr_file="i386/t-gthr-win32"
 	    ;;
 	  posix)
-	    tmake_file="i386/t-mingw-pthread $tmake_file"
+	    tmake_thr_file="i386/t-mingw-pthread"
 	    ;;
 	  mcf)
-	    tmake_file="i386/t-mingw-mcfgthread $tmake_file"
+	    tmake_thr_file="i386/t-mingw-mcfgthread"
 	    ;;
 	esac
 	# This has to match the logic for DWARF2_UNWIND_INFO in gcc/config/i386/cygming.h
@@ -872,7 +872,7 @@ x86_64-*-mingw*)
 	else
 		tmake_dlldir_file="i386/t-dlldir-x"
 	fi
-	tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_dlldir_file} i386/t-slibgcc-cygming i386/t-cygming i386/t-mingw32 t-dfprules t-crtfm i386/t-chkstk"
+	tmake_file="${tmake_file} ${tmake_eh_file} ${tmake_thr_file} ${tmake_dlldir_file} i386/t-slibgcc-cygming i386/t-slibgcc-mingw i386/t-cygming i386/t-mingw32 t-dfprules t-crtfm i386/t-chkstk"
 	extra_parts="$extra_parts crtbegin.o crtend.o crtfastmath.o"
 	if test x$enable_vtable_verify = xyes; then
 		extra_parts="$extra_parts vtv_start.o vtv_end.o vtv_start_preinit.o vtv_end_preinit.o"
diff --git a/libgcc/config/i386/gthr-win32-cond.c b/libgcc/config/i386/gthr-win32-cond.c
new file mode 100644
index 00000000000..6b6fb45d5d3
--- /dev/null
+++ b/libgcc/config/i386/gthr-win32-cond.c
@@ -0,0 +1,89 @@
+/* Implementation of threads compatibility routines for libgcc2.  */
+
+/* Copyright (C) 1999-2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* This module is separate from the rest of the implementation because it
+   references symbols in system libraries that are only available on Vista
+   and Server 2008 or later versions.  */
+
+/* Get the out-of-line version of the inline routines.  */
+
+#if _WIN32_WINNT < 0x0600
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0600
+#endif
+
+#define __GTHREAD_WIN32_COND_INLINE
+
+#define __gthread_cond_init_function __gthr_win32_cond_init_function
+#define __gthread_cond_broadcast __gthr_win32_cond_broadcast
+#define __gthread_cond_signal __gthr_win32_cond_signal
+#define __gthread_cond_wait __gthr_win32_cond_wait
+#define __gthread_cond_timedwait __gthr_win32_cond_timedwait
+
+#include "gthr-win32.h"
+
+/* The number of 100-nanoseconds between 1/1/1601 and 1/1/1970. */
+#define FILETIME_1970 116444736000000000ULL
+
+/* The number of 100-nanoseconds per second.  */
+#define NSEC100_PER_SEC (1000000000ULL / 100)
+
+/* The number of 100-nanoseconds per millisecond.  */
+#define NSEC100_PER_MSEC (NSEC100_PER_SEC / 1000)
+
+/* The ceiling division of X by Y.  */
+#define CEIL_DIV(X, Y) (((X) + (Y) - 1) / (Y))
+
+/* Convert absolute thread time to relative time in millisecond.  */
+
+DWORD
+__gthr_win32_abs_to_rel_time (const __gthread_time_t *abs_time)
+{
+  union {
+    ULONGLONG nsec100;
+    FILETIME ft;
+  } now;
+  ULONGLONG abs_time_nsec100;
+
+  /* The Windows epoch is 1/1/1601 while the Unix epoch is 1/1/1970.  */
+  GetSystemTimeAsFileTime (&now.ft);
+  now.nsec100 -= FILETIME_1970;
+
+  abs_time_nsec100
+    = (ULONGLONG) abs_time->tv_sec * NSEC100_PER_SEC
+	+ CEIL_DIV (abs_time->tv_nsec, 100);
+
+  if (abs_time_nsec100 < now.nsec100)
+    return 0;
+
+  return (DWORD) CEIL_DIV (abs_time_nsec100 - now.nsec100, NSEC100_PER_SEC);
+}
+
+/* Check the sizes of the local version of the Win32 types.  */
+
+#define CHECK_SIZE_OF(TYPE) \
+  typedef int assertion[sizeof(__gthr_win32_##TYPE) == sizeof(TYPE) ? 1 : -1];
+
+CHECK_SIZE_OF (CONDITION_VARIABLE)
diff --git a/libgcc/config/i386/gthr-win32-thread.c b/libgcc/config/i386/gthr-win32-thread.c
new file mode 100644
index 00000000000..81e6fd094c7
--- /dev/null
+++ b/libgcc/config/i386/gthr-win32-thread.c
@@ -0,0 +1,162 @@
+/* Implementation of threads compatibility routines for libgcc2.  */
+
+/* Copyright (C) 1999-2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* This module is separate from the rest of the implementation because only
+   one copy of it ought to be linked.  */
+
+/* The implementation strategy for the c++0x thread support is as follows.
+
+   A GNU thread is represented by a Win32 HANDLE that is obtained when the
+   Win32 thread is created, except of course for the initial thread.  This
+   Win32 HANDLE is stored in a descriptor keyed from TLS memory for every
+   thread, so the self routine can return it instead of having to duplicate
+   the pseudo-handle returned by GetCurrentThread each time it is invoked.
+   For the initial thread, this Win32 HANDLE is created during the first
+   call to the self routine using the aforementioned technique.
+
+   Note that the equal routine compares the identifier of threads instead
+   of their Win32 HANDLE, which will give the correct positive answer even
+   in the case where distinct Win32 HANDLEs have been created for the same
+   thread by multiple instances of libgcc included in the link.  */
+
+#include "gthr-win32.h"
+
+/* The thread descriptor keyed from TLS memory.  */
+struct __gthr_win32_thr_desc
+{
+  void *(*func) (void*);
+  void *args;
+  HANDLE h;
+};
+
+/* The TLS key used by one instance of the library.  */
+static __gthread_key_t __gthr_win32_tls = TLS_OUT_OF_INDEXES;
+
+/* The initialization device for the TLS key.  */
+static __gthread_once_t __gthr_win32_tls_once = __GTHREAD_ONCE_INIT;
+
+/* Initialize the TLS key.  */
+
+static void
+__gthr_win32_tls_init (void)
+{
+  if (__gthread_key_create (&__gthr_win32_tls, free))
+    abort ();
+}
+
+/* Wrapper routine around thread functions.  */
+
+static DWORD
+__gthr_win32_thread_wrapper (void *args)
+{
+  struct __gthr_win32_thr_desc *td = (struct __gthr_win32_thr_desc *) args;
+
+  __gthread_setspecific (__gthr_win32_tls, td);
+
+  DWORD exit_code = (DWORD) (ULONG_PTR) (*td->func) (td->args);
+
+  ExitThread (exit_code);
+  return exit_code;
+}
+
+/* Implement the __gthread_create routine.  */
+
+int
+__gthr_win32_create (__gthread_t *thr, void *(*func) (void*), void *args)
+{
+  struct __gthr_win32_thr_desc *td;
+
+  __gthread_once (&__gthr_win32_tls_once, __gthr_win32_tls_init);
+
+  td = malloc (sizeof (struct __gthr_win32_thr_desc));
+  td->func = func;
+  td->args = args;
+  td->h = CreateThread (NULL, 0,
+			(LPTHREAD_START_ROUTINE) __gthr_win32_thread_wrapper,
+			(LPVOID) td, CREATE_SUSPENDED, NULL);
+  if (td->h)
+    {
+      ResumeThread (td->h);
+      *thr = (__gthread_t) td->h;
+      return 0;
+    }
+  else
+    {
+      free (td);
+      return (int) GetLastError ();
+    }
+}
+
+/* Implement the __gthread_join routine.  */
+
+int
+__gthr_win32_join (__gthread_t thr, void **value_ptr)
+{
+  int status = 0;
+
+  if (GetThreadId ((HANDLE) thr) == GetCurrentThreadId ())
+    return 1;
+
+  if (WaitForSingleObject ((HANDLE) thr, INFINITE) == WAIT_OBJECT_0)
+    {
+      if (value_ptr)
+	{
+	  DWORD exit_code;
+	  if (GetExitCodeThread ((HANDLE) thr, &exit_code))
+	    *value_ptr = (void *) (ULONG_PTR) exit_code;
+	  else
+	    status = (int) GetLastError ();
+	}
+    }
+  else
+    status = (int) GetLastError ();
+
+  CloseHandle ((HANDLE) thr);
+  return status;
+}
+
+/* Implement the __gthread_self routine.  */
+
+__gthread_t
+__gthr_win32_self (void)
+{
+  struct __gthr_win32_thr_desc *td;
+
+  __gthread_once (&__gthr_win32_tls_once, __gthr_win32_tls_init);
+
+  if (!(td = __gthread_getspecific (__gthr_win32_tls)))
+    {
+      HANDLE proc = GetCurrentProcess ();
+      td = malloc (sizeof (struct __gthr_win32_thr_desc));
+      td->func = NULL;
+      td->args = NULL;
+      if (!DuplicateHandle (proc, GetCurrentThread(), proc, &td->h, 0, FALSE,
+			    DUPLICATE_SAME_ACCESS))
+	abort ();
+      __gthread_setspecific (__gthr_win32_tls, td);
+    }
+
+  return td->h;
+}
diff --git a/libgcc/config/i386/gthr-win32.c b/libgcc/config/i386/gthr-win32.c
index fad8f8aca1e..df06e20d18a 100644
--- a/libgcc/config/i386/gthr-win32.c
+++ b/libgcc/config/i386/gthr-win32.c
@@ -1,10 +1,6 @@
-/* Implementation of W32-specific threads compatibility routines for
-   libgcc2.  */
+/* Implementation of threads compatibility routines for libgcc2.  */
 
 /* Copyright (C) 1999-2022 Free Software Foundation, Inc.
-   Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
-   Modified and moved to separate file by Danny Smith
-   <dannysmith@users.sourceforge.net>.
 
 This file is part of GCC.
 
@@ -27,239 +23,33 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#include <windows.h>
-#ifndef __GTHREAD_HIDE_WIN32API
-# define __GTHREAD_HIDE_WIN32API 1
-#endif
-#include "gthr-win32.h"
-
-/* Windows32 threads specific definitions. The windows32 threading model
-   does not map well into pthread-inspired gcc's threading model, and so 
-   there are caveats one needs to be aware of.
-
-   1. The destructor supplied to __gthread_key_create is ignored for
-      generic x86-win32 ports. This will certainly cause memory leaks 
-      due to unreclaimed eh contexts (sizeof (eh_context) is at least 
-      24 bytes for x86 currently).
-
-      This memory leak may be significant for long-running applications
-      that make heavy use of C++ EH.
-
-      However, Mingw runtime (version 0.3 or newer) provides a mechanism
-      to emulate pthreads key dtors; the runtime provides a special DLL,
-      linked in if -mthreads option is specified, that runs the dtors in
-      the reverse order of registration when each thread exits. If
-      -mthreads option is not given, a stub is linked in instead of the
-      DLL, which results in memory leak. Other x86-win32 ports can use 
-      the same technique of course to avoid the leak.
-
-   2. The error codes returned are non-POSIX like, and cast into ints.
-      This may cause incorrect error return due to truncation values on 
-      hw where sizeof (DWORD) > sizeof (int).
-   
-   3. We are currently using a special mutex instead of the Critical
-      Sections, since Win9x does not support TryEnterCriticalSection
-      (while NT does).
-  
-   The basic framework should work well enough. In the long term, GCC
-   needs to use Structured Exception Handling on Windows32.  */
-
-int
-__gthr_win32_once (__gthread_once_t *once, void (*func) (void))
-{
-  if (once == NULL || func == NULL)
-    return EINVAL;
-
-  if (! once->done)
-    {
-      if (InterlockedIncrement (&(once->started)) == 0)
-        {
-	  (*func) ();
-	  once->done = TRUE;
-	}
-      else
-	{
-	  /* Another thread is currently executing the code, so wait for it 
-	     to finish; yield the CPU in the meantime.  If performance 
-	     does become an issue, the solution is to use an Event that 
-	     we wait on here (and set above), but that implies a place to 
-	     create the event before this routine is called.  */ 
-	  while (! once->done)
-	    Sleep (0);
-	}
-    }
-  return 0;
-}
-
-/* Windows32 thread local keys don't support destructors; this leads to
-   leaks, especially in threaded applications making extensive use of 
-   C++ EH. Mingw uses a thread-support DLL to work-around this problem.  */
-
-int
-__gthr_win32_key_create (__gthread_key_t *key,
-			 void (*dtor) (void *) __attribute__((unused)))
-{
-  int status = 0;
-  DWORD tls_index = TlsAlloc ();
-  if (tls_index != 0xFFFFFFFF)
-    {
-      *key = tls_index;
-#ifdef MINGW32_SUPPORTS_MT_EH
-      /* Mingw runtime will run the dtors in reverse order for each thread
-         when the thread exits.  */
-      status = __mingwthr_key_dtor (*key, dtor);
-#endif
-    }
-  else
-    status = (int) GetLastError ();
-  return status;
-}
-
-int
-__gthr_win32_key_delete (__gthread_key_t key)
-{
-  return (TlsFree (key) != 0) ? 0 : (int) GetLastError ();
-}
-
-void *
-__gthr_win32_getspecific (__gthread_key_t key)
-{
-  DWORD lasterror;
-  void *ptr;
-  lasterror = GetLastError();
-  ptr = TlsGetValue(key);
-  SetLastError( lasterror );
-  return ptr;
-}
+/* Get the out-of-line version of the inline routines.  */
+
+#define __GTHREAD_WIN32_ACTIVE_P() 1
+#define __GTHREAD_WIN32_INLINE
+
+#define __gthread_detach __gthr_win32_detach
+#define __gthread_equal __gthr_win32_equal
+#define __gthread_yield __gthr_win32_yield
+#define __gthread_once __gthr_win32_once
+#define __gthread_key_create __gthr_win32_key_create
+#define __gthread_key_delete __gthr_win32_key_delete
+#define __gthread_getspecific __gthr_win32_getspecific
+#define __gthread_setspecific __gthr_win32_setspecific
+#define __gthread_mutex_init_function __gthr_win32_mutex_init_function
+#define __gthread_mutex_destroy __gthr_win32_mutex_destroy
+#define __gthread_mutex_lock __gthr_win32_mutex_lock
+#define __gthread_mutex_trylock __gthr_win32_mutex_trylock
+#define __gthread_mutex_unlock __gthr_win32_mutex_unlock
+#define __gthread_recursive_mutex_trylock __gthr_win32_recursive_mutex_trylock
 
-int
-__gthr_win32_setspecific (__gthread_key_t key, const void *ptr)
-{
-  if (TlsSetValue (key, CONST_CAST2(void *, const void *, ptr)) != 0)
-    return 0;
-  else
-    return GetLastError ();
-}
-
-void
-__gthr_win32_mutex_init_function (__gthread_mutex_t *mutex)
-{
-  mutex->counter = -1;
-  mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
-}
-
-void
-__gthr_win32_mutex_destroy (__gthread_mutex_t *mutex)
-{
-  CloseHandle ((HANDLE) mutex->sema);
-}
-
-int
-__gthr_win32_mutex_lock (__gthread_mutex_t *mutex)
-{
-  if (InterlockedIncrement (&mutex->counter) == 0 ||
-      WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
-    return 0;
-  else
-    {
-      /* WaitForSingleObject returns WAIT_FAILED, and we can only do
-         some best-effort cleanup here.  */
-      InterlockedDecrement (&mutex->counter);
-      return 1;
-    }
-}
-
-int
-__gthr_win32_mutex_trylock (__gthread_mutex_t *mutex)
-{
-  if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
-    return 0;
-  else
-    return 1;
-}
-
-int
-__gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
-{
-  if (InterlockedDecrement (&mutex->counter) >= 0)
-    return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
-  else
-    return 0;
-}
-
-void
-__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
-{
-  mutex->counter = -1;
-  mutex->depth = 0;
-  mutex->owner = 0;
-  mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
-}
-
-int
-__gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
-{
-  DWORD me = GetCurrentThreadId();
-  if (InterlockedIncrement (&mutex->counter) == 0)
-    {
-      mutex->depth = 1;
-      mutex->owner = me;
-    }
-  else if (mutex->owner == me)
-    {
-      InterlockedDecrement (&mutex->counter);
-      ++(mutex->depth);
-    }
-  else if (WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
-    {
-      mutex->depth = 1;
-      mutex->owner = me;
-    }
-  else
-    {
-      /* WaitForSingleObject returns WAIT_FAILED, and we can only do
-         some best-effort cleanup here.  */
-      InterlockedDecrement (&mutex->counter);
-      return 1;
-    }
-  return 0;
-}
-
-int
-__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
-{
-  DWORD me = GetCurrentThreadId();
-  if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
-    {
-      mutex->depth = 1;
-      mutex->owner = me;
-    }
-  else if (mutex->owner == me)
-    ++(mutex->depth);
-  else
-    return 1;
-
-  return 0;
-}
-
-int
-__gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
-{
-  --(mutex->depth);
-  if (mutex->depth == 0)
-    {
-      mutex->owner = 0;
+#include "gthr-win32.h"
 
-      if (InterlockedDecrement (&mutex->counter) >= 0)
-	return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
-    }
+/* Check the sizes of the local version of the Win32 types.  */
 
-  return 0;
-}
+#define CHECK_SIZE_OF(TYPE) \
+  typedef int assertion[sizeof(__gthr_win32_##TYPE) == sizeof(TYPE) ? 1 : -1];
 
-int
-__gthr_win32_recursive_mutex_destroy (__gthread_recursive_mutex_t *mutex)
-{
-  CloseHandle ((HANDLE) mutex->sema);
-  return 0;
-}
+CHECK_SIZE_OF (DWORD)
+CHECK_SIZE_OF (HANDLE)
+CHECK_SIZE_OF (CRITICAL_SECTION)
diff --git a/libgcc/config/i386/gthr-win32.h b/libgcc/config/i386/gthr-win32.h
index 6f70e9b9dea..9485dd50bf9 100644
--- a/libgcc/config/i386/gthr-win32.h
+++ b/libgcc/config/i386/gthr-win32.h
@@ -28,18 +28,15 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #ifndef GCC_GTHR_WIN32_H
 #define GCC_GTHR_WIN32_H
 
-/* Make sure CONST_CAST2 (origin in system.h) is declared.  */
-#ifndef CONST_CAST2
-#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
-#endif
+/* So we can test Windows version numbers.  */
+#include <stdlib.h>
 
-/* Windows32 threads specific definitions. The windows32 threading model
-   does not map well into pthread-inspired gcc's threading model, and so
-   there are caveats one needs to be aware of.
+/* The Windows threading model does not map well into the POSIX inspired
+   GCC threading model, so there are caveats one needs to be aware of.
 
    1. The destructor supplied to __gthread_key_create is ignored for
-      generic x86-win32 ports. This will certainly cause memory leaks
-      due to unreclaimed eh contexts (sizeof (eh_context) is at least
+      generic Windows ports.  This will certainly cause memory leaks
+      due to unreclaimed EH contexts (sizeof (eh_context) is at least
       24 bytes for x86 currently).
 
       This memory leak may be significant for long-running applications
@@ -50,29 +47,41 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
       linked in if -mthreads option is specified, that runs the dtors in
       the reverse order of registration when each thread exits. If
       -mthreads option is not given, a stub is linked in instead of the
-      DLL, which results in memory leak. Other x86-win32 ports can use
+      DLL, which results in memory leak.  Other Windows ports can use
       the same technique of course to avoid the leak.
 
    2. The error codes returned are non-POSIX like, and cast into ints.
       This may cause incorrect error return due to truncation values on
       hw where sizeof (DWORD) > sizeof (int).
 
-   3. We are currently using a special mutex instead of the Critical
-      Sections, since Win9x does not support TryEnterCriticalSection
-      (while NT does).
+   3. POSIX-like condition variables are supported, but only on Vista and
+      Server 2008 or later versions.
 
-   The basic framework should work well enough. In the long term, GCC
-   needs to use Structured Exception Handling on Windows32.  */
+   4. Timed lock primitives are not supported.  */
 
 #define __GTHREADS 1
 
-#include <errno.h>
-#ifdef __MINGW32__
-#include <_mingw.h>
+/* Condition variables are supported on Vista and Server 2008 or later.  */
+#if _WIN32_WINNT >= 0x0600
+#define __GTHREAD_HAS_COND 1
+#define __GTHREADS_CXX0X 1
+#endif
+
+#if _GTHREAD_USE_MUTEX_TIMEDLOCK
+#error Timed lock primitives are not supported on Windows targets
+#endif
+
+/* Make sure CONST_CAST2 (origin in system.h) is declared.  */
+#ifndef CONST_CAST2
+#ifdef __cplusplus
+#define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast<TOTYPE> (X))
+#else
+#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((__extension__(union {FROMTYPE _q; TOTYPE _nq;})(X))._nq)
+#endif
 #endif
 
-#ifndef __UNUSED_PARAM
-#define __UNUSED_PARAM(x) x
+#ifndef ATTRIBUTE_UNUSED
+#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
 #endif
 
 #ifdef _LIBOBJC
@@ -82,12 +91,13 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #ifndef __OBJC__
 #define __OBJC__
 #endif
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
 /* Now undef the windows BOOL.  */
 #undef BOOL
 
 /* Key structure for maintaining thread specific storage */
-static DWORD	__gthread_objc_data_tls = (DWORD) -1;
+static DWORD __gthread_objc_data_tls = TLS_OUT_OF_INDEXES;
 
 /* Backend initialization functions */
 
@@ -96,7 +106,7 @@ int
 __gthread_objc_init_thread_system (void)
 {
   /* Initialize the thread storage key.  */
-  if ((__gthread_objc_data_tls = TlsAlloc ()) != (DWORD) -1)
+  if ((__gthread_objc_data_tls = TlsAlloc ()) != TLS_OUT_OF_INDEXES)
     return 0;
   else
     return -1;
@@ -106,7 +116,7 @@ __gthread_objc_init_thread_system (void)
 int
 __gthread_objc_close_thread_system (void)
 {
-  if (__gthread_objc_data_tls != (DWORD) -1)
+  if (__gthread_objc_data_tls != TLS_OUT_OF_INDEXES)
     TlsFree (__gthread_objc_data_tls);
   return 0;
 }
@@ -222,15 +232,9 @@ __gthread_objc_thread_set_data (void *value)
 void *
 __gthread_objc_thread_get_data (void)
 {
-  DWORD lasterror;
-  void *ptr;
-
-  lasterror = GetLastError ();
-
-  ptr = TlsGetValue (__gthread_objc_data_tls);          /* Return thread data.  */
-
+  DWORD lasterror = GetLastError ();
+  void * ptr = TlsGetValue (__gthread_objc_data_tls);
   SetLastError (lasterror);
-
   return ptr;
 }
 
@@ -294,7 +298,7 @@ __gthread_objc_mutex_unlock (objc_mutex_t mutex)
 
 /* Allocate a condition.  */
 int
-__gthread_objc_condition_allocate (objc_condition_t __UNUSED_PARAM(condition))
+__gthread_objc_condition_allocate (objc_condition_t condition ATTRIBUTE_UNUSED)
 {
   /* Unimplemented.  */
   return -1;
@@ -302,7 +306,7 @@ __gthread_objc_condition_allocate (objc_condition_t __UNUSED_PARAM(condition))
 
 /* Deallocate a condition.  */
 int
-__gthread_objc_condition_deallocate (objc_condition_t __UNUSED_PARAM(condition))
+__gthread_objc_condition_deallocate (objc_condition_t condition ATTRIBUTE_UNUSED)
 {
   /* Unimplemented.  */
   return -1;
@@ -310,8 +314,8 @@ __gthread_objc_condition_deallocate (objc_condition_t __UNUSED_PARAM(condition))
 
 /* Wait on the condition */
 int
-__gthread_objc_condition_wait (objc_condition_t __UNUSED_PARAM(condition),
-			       objc_mutex_t __UNUSED_PARAM(mutex))
+__gthread_objc_condition_wait (objc_condition_t condition ATTRIBUTE_UNUSED,
+			       objc_mutex_t mutex ATTRIBUTE_UNUSED)
 {
   /* Unimplemented.  */
   return -1;
@@ -319,7 +323,7 @@ __gthread_objc_condition_wait (objc_condition_t __UNUSED_PARAM(condition),
 
 /* Wake up all threads waiting on this condition.  */
 int
-__gthread_objc_condition_broadcast (objc_condition_t __UNUSED_PARAM(condition))
+__gthread_objc_condition_broadcast (objc_condition_t condition ATTRIBUTE_UNUSED)
 {
   /* Unimplemented.  */
   return -1;
@@ -327,7 +331,7 @@ __gthread_objc_condition_broadcast (objc_condition_t __UNUSED_PARAM(condition))
 
 /* Wake up one thread waiting on this condition.  */
 int
-__gthread_objc_condition_signal (objc_condition_t __UNUSED_PARAM(condition))
+__gthread_objc_condition_signal (objc_condition_t condition ATTRIBUTE_UNUSED)
 {
   /* Unimplemented.  */
   return -1;
@@ -335,35 +339,46 @@ __gthread_objc_condition_signal (objc_condition_t __UNUSED_PARAM(condition))
 
 #else /* _LIBOBJC */
 
+/* For struct timespec.  Do not include <sys/time.h> here since Gnulib provides
+   its own version which drags the Win32 API definitions.  */
+#include <sys/timeb.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef unsigned long __gthread_key_t;
+typedef unsigned int __gthr_win32_DWORD;
+typedef void *__gthr_win32_HANDLE;
 
 typedef struct {
-  int done;
-  long started;
-} __gthread_once_t;
+  void *DebugInfo;
+  int LockCount;
+  int RecursionCount;
+  __gthr_win32_HANDLE OwningThread;
+  __gthr_win32_HANDLE LockSemaphore;
+  void *SpinCount;
+} __gthr_win32_CRITICAL_SECTION;
 
 typedef struct {
-  long counter;
-  void *sema;
-} __gthread_mutex_t;
-
-typedef struct {
-  long counter;
-  long depth;
-  unsigned long owner;
-  void *sema;
-} __gthread_recursive_mutex_t;
+  void *Ptr;
+} __gthr_win32_CONDITION_VARIABLE;
+
+typedef __gthr_win32_HANDLE __gthread_t;
+typedef __gthr_win32_DWORD __gthread_key_t;
+typedef struct { int done; long started; } __gthread_once_t;
+typedef __gthr_win32_CRITICAL_SECTION __gthread_mutex_t;
+typedef __gthr_win32_CRITICAL_SECTION __gthread_recursive_mutex_t;
+#if __GTHREAD_HAS_COND
+typedef __gthr_win32_CONDITION_VARIABLE __gthread_cond_t;
+#endif
+typedef struct timespec __gthread_time_t;
 
 #define __GTHREAD_ONCE_INIT {0, -1}
 #define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function
-#define __GTHREAD_MUTEX_INIT_DEFAULT {-1, 0}
 #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION \
   __gthread_recursive_mutex_init_function
-#define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0}
+#define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function
+#define __GTHREAD_TIME_INIT {0, 0}
 
 #if defined (_WIN32) && !defined(__CYGWIN__)
 #define MINGW32_SUPPORTS_MT_EH 1
@@ -388,30 +403,74 @@ __gthread_active_p (void)
 #endif
 }
 
-#if __GTHREAD_HIDE_WIN32API
-
-/* The implementations are in config/i386/gthr-win32.c in libgcc.a.
-   Only stubs are exposed to avoid polluting the C++ namespace with
-   windows api definitions.  */
-
+extern int __gthr_win32_create (__gthread_t *, void *(*) (void*), void *);
+extern int __gthr_win32_join (__gthread_t, void **);
+extern __gthread_t __gthr_win32_self (void);
 extern int __gthr_win32_once (__gthread_once_t *, void (*) (void));
+extern int __gthr_win32_detach (__gthread_t);
+extern int __gthr_win32_equal (__gthread_t, __gthread_t);
+extern int __gthr_win32_yield (void);
 extern int __gthr_win32_key_create (__gthread_key_t *, void (*) (void*));
 extern int __gthr_win32_key_delete (__gthread_key_t);
 extern void * __gthr_win32_getspecific (__gthread_key_t);
 extern int __gthr_win32_setspecific (__gthread_key_t, const void *);
 extern void __gthr_win32_mutex_init_function (__gthread_mutex_t *);
+extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *);
 extern int __gthr_win32_mutex_lock (__gthread_mutex_t *);
 extern int __gthr_win32_mutex_trylock (__gthread_mutex_t *);
 extern int __gthr_win32_mutex_unlock (__gthread_mutex_t *);
-extern void
-  __gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *);
-extern int __gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *);
-extern int
-  __gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *);
-extern int __gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *);
-extern void __gthr_win32_mutex_destroy (__gthread_mutex_t *);
-extern int
-  __gthr_win32_recursive_mutex_destroy (__gthread_recursive_mutex_t *);
+extern int __gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *);
+#if __GTHREAD_HAS_COND
+extern void __gthr_win32_cond_init_function (__gthread_cond_t *);
+extern int __gthr_win32_cond_broadcast (__gthread_cond_t *);
+extern int __gthr_win32_cond_signal (__gthread_cond_t *);
+extern int __gthr_win32_cond_wait (__gthread_cond_t *, __gthread_mutex_t *);
+extern int __gthr_win32_cond_timedwait (__gthread_cond_t *, __gthread_mutex_t *,
+					const __gthread_time_t *);
+#endif
+
+static inline int
+__gthread_create (__gthread_t *__thr, void *(*__func) (void*),
+		  void *__args)
+{
+  return __gthr_win32_create (__thr, __func, __args);
+}
+
+static inline int
+__gthread_join (__gthread_t __thr, void **__value_ptr)
+{
+  return __gthr_win32_join (__thr, __value_ptr);
+}
+
+static inline __gthread_t
+__gthread_self (void)
+{
+  return __gthr_win32_self ();
+}
+
+#if __GTHREAD_HIDE_WIN32API
+
+/* The implementations are in config/i386/gthr-win32.c in libgcc.a.
+   Only stubs are exposed to avoid polluting the C++ namespace with
+   Win32 API definitions.  */
+
+static inline int
+__gthread_detach (__gthread_t __thr)
+{
+  return __gthr_win32_detach (__thr);
+}
+
+static inline int
+__gthread_equal (__gthread_t __thr1, __gthread_t __thr2)
+{
+  return __gthr_win32_equal (__thr1, __thr2);
+}
+
+static inline int
+__gthread_yield (void)
+{
+  return __gthr_win32_yield ();
+}
 
 static inline int
 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
@@ -485,279 +544,320 @@ __gthread_mutex_unlock (__gthread_mutex_t *__mutex)
     return 0;
 }
 
+static inline int
+__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
+{
+  if (__gthread_active_p ())
+    return __gthr_win32_recursive_mutex_trylock (__mutex);
+  else
+    return 0;
+}
+
+#if __GTHREAD_HAS_COND
+
 static inline void
-__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
+__gthread_cond_init_function (__gthread_cond_t *__cond)
 {
-   __gthr_win32_recursive_mutex_init_function (__mutex);
+  __gthr_win32_cond_init_function (__cond);
 }
 
 static inline int
-__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
+__gthread_cond_broadcast (__gthread_cond_t *__cond)
 {
-  if (__gthread_active_p ())
-    return __gthr_win32_recursive_mutex_lock (__mutex);
-  else
-    return 0;
+  return __gthr_win32_cond_broadcast (__cond);
 }
 
 static inline int
-__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
+__gthread_cond_signal (__gthread_cond_t *__cond)
 {
-  if (__gthread_active_p ())
-    return __gthr_win32_recursive_mutex_trylock (__mutex);
-  else
-    return 0;
+  return __gthr_win32_cond_signal (__cond);
 }
 
 static inline int
-__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
+__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
 {
-  if (__gthread_active_p ())
-    return __gthr_win32_recursive_mutex_unlock (__mutex);
-  else
-    return 0;
+  return __gthr_win32_cond_wait (__cond, __mutex);
 }
 
 static inline int
-__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
+__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex,
+			  const __gthread_time_t *__abs_time)
 {
-  return __gthr_win32_recursive_mutex_destroy (__mutex);
+  return __gthr_win32_cond_timedwait (__cond, __mutex, __abs_time);
 }
 
+#endif /* __GTHREAD_HAS_COND */
+
 #else /* ! __GTHREAD_HIDE_WIN32API */
 
-#define NOGDI
+#ifndef __GTHREAD_WIN32_INLINE
+#define __GTHREAD_WIN32_INLINE static inline
+#endif
+
+#ifndef __GTHREAD_WIN32_COND_INLINE
+#define __GTHREAD_WIN32_COND_INLINE static inline
+#endif
+
+#ifndef __GTHREAD_WIN32_ACTIVE_P
+#define __GTHREAD_WIN32_ACTIVE_P __gthread_active_p
+#endif
+
+#define WIN32_LEAN_AND_MEAN
 #include <windows.h>
-#include <errno.h>
 
-static inline int
+__GTHREAD_WIN32_INLINE int
+__gthread_detach (__gthread_t __thr)
+{
+  CloseHandle ((HANDLE) __thr);
+  return 0;
+}
+
+__GTHREAD_WIN32_INLINE int
+__gthread_equal (__gthread_t __t1, __gthread_t __t2)
+{
+  return GetThreadId ((HANDLE) __t1) == GetThreadId ((HANDLE) __t2);
+}
+
+__GTHREAD_WIN32_INLINE int
+__gthread_yield (void)
+{
+  Sleep (0);
+  return 0;
+}
+
+__GTHREAD_WIN32_INLINE int
 __gthread_once (__gthread_once_t *__once, void (*__func) (void))
 {
-  if (! __gthread_active_p ())
+  if (!__GTHREAD_WIN32_ACTIVE_P ())
     return -1;
-  else if (__once == NULL || __func == NULL)
-    return EINVAL;
 
-  if (! __once->done)
+  if (__builtin_expect (!__once->done, 0))
     {
-      if (InterlockedIncrement (&(__once->started)) == 0)
+      /* We rely on the memory model of the x86 architecture where every load
+	 has acquire semantics and every store has release semantics.  */
+      if (__atomic_add_fetch (&__once->started, 1, __ATOMIC_ACQ_REL) == 0)
 	{
 	  (*__func) ();
-	  __once->done = TRUE;
+	  __once->done = 1;
 	}
       else
 	{
 	  /* Another thread is currently executing the code, so wait for it
-	     to finish; yield the CPU in the meantime.  If performance
+	     to finish and yield the CPU in the meantime.  If performance
 	     does become an issue, the solution is to use an Event that
 	     we wait on here (and set above), but that implies a place to
 	     create the event before this routine is called.  */
-	  while (! __once->done)
-	    Sleep (0);
+	  while (!__once->done)
+	    __gthread_yield ();
 	}
     }
 
   return 0;
 }
 
-/* Windows32 thread local keys don't support destructors; this leads to
+/* Windows thread local keys don't support destructors; this leads to
    leaks, especially in threaded applications making extensive use of
    C++ EH. Mingw uses a thread-support DLL to work-around this problem.  */
-static inline int
+__GTHREAD_WIN32_INLINE int
 __gthread_key_create (__gthread_key_t *__key,
-		      void (*__dtor) (void *) __attribute__((__unused__)))
+		      void (*__dtor) (void *) ATTRIBUTE_UNUSED)
 {
-  int __status = 0;
   DWORD __tls_index = TlsAlloc ();
-  if (__tls_index != 0xFFFFFFFF)
+  if (__tls_index != TLS_OUT_OF_INDEXES)
     {
       *__key = __tls_index;
 #ifdef MINGW32_SUPPORTS_MT_EH
       /* Mingw runtime will run the dtors in reverse order for each thread
          when the thread exits.  */
-      __status = __mingwthr_key_dtor (*__key, __dtor);
+      return __mingwthr_key_dtor (*__key, __dtor);
+#else
+      return 0;
 #endif
     }
   else
-    __status = (int) GetLastError ();
-  return __status;
+    return (int) GetLastError ();
 }
 
-static inline int
+__GTHREAD_WIN32_INLINE int
 __gthread_key_delete (__gthread_key_t __key)
 {
-  return (TlsFree (__key) != 0) ? 0 : (int) GetLastError ();
+  if (TlsFree (__key))
+    return 0;
+  else
+    return (int) GetLastError ();
 }
 
-static inline void *
+__GTHREAD_WIN32_INLINE void *
 __gthread_getspecific (__gthread_key_t __key)
 {
-  DWORD __lasterror;
-  void *__ptr;
-
-  __lasterror = GetLastError ();
-
-  __ptr = TlsGetValue (__key);
-
+  DWORD __lasterror = GetLastError ();
+  void *__ptr = TlsGetValue (__key);
   SetLastError (__lasterror);
-
   return __ptr;
 }
 
-static inline int
+__GTHREAD_WIN32_INLINE int
 __gthread_setspecific (__gthread_key_t __key, const void *__ptr)
 {
-  if (TlsSetValue (__key, CONST_CAST2(void *, const void *, __ptr)) != 0)
+  if (TlsSetValue (__key, CONST_CAST2(void *, const void *, __ptr)))
     return 0;
   else
-    return GetLastError ();
+    return (int) GetLastError ();
 }
 
-static inline void
+__GTHREAD_WIN32_INLINE void
 __gthread_mutex_init_function (__gthread_mutex_t *__mutex)
 {
-  __mutex->counter = -1;
-  __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
+  InitializeCriticalSection ((LPCRITICAL_SECTION) __mutex);
 }
 
-static inline void
+__GTHREAD_WIN32_INLINE void
 __gthread_mutex_destroy (__gthread_mutex_t *__mutex)
 {
-  CloseHandle ((HANDLE) __mutex->sema);
+  DeleteCriticalSection ((LPCRITICAL_SECTION) __mutex);
 }
 
-static inline int
+__GTHREAD_WIN32_INLINE int
 __gthread_mutex_lock (__gthread_mutex_t *__mutex)
 {
-  int __status = 0;
+  if (__GTHREAD_WIN32_ACTIVE_P ())
+    EnterCriticalSection ((LPCRITICAL_SECTION) __mutex);
+  return 0;
+}
 
-  if (__gthread_active_p ())
+__GTHREAD_WIN32_INLINE int
+__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
+{
+  if (__GTHREAD_WIN32_ACTIVE_P ())
     {
-      if (InterlockedIncrement (&__mutex->counter) == 0 ||
-	  WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
-	__status = 0;
-      else
+      BOOL __ret = TryEnterCriticalSection ((LPCRITICAL_SECTION) __mutex);
+      if (__ret)
 	{
-	  /* WaitForSingleObject returns WAIT_FAILED, and we can only do
-	     some best-effort cleanup here.  */
-	  InterlockedDecrement (&__mutex->counter);
-	  __status = 1;
+	  if (__mutex->RecursionCount > 1)
+	    {
+	      LeaveCriticalSection ((LPCRITICAL_SECTION) __mutex);
+	      return 1;
+	    }
+	  else
+	    return 0;
 	}
+      else
+	return 1;
     }
-  return __status;
+  else
+    return 0;
 }
 
-static inline int
-__gthread_mutex_trylock (__gthread_mutex_t *__mutex)
+__GTHREAD_WIN32_INLINE int
+__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
 {
-  int __status = 0;
+  if (__GTHREAD_WIN32_ACTIVE_P ())
+    LeaveCriticalSection ((LPCRITICAL_SECTION) __mutex);
+  return 0;
+}
 
-  if (__gthread_active_p ())
-    {
-      if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
-	__status = 0;
-      else
-	__status = 1;
-    }
-  return __status;
+__GTHREAD_WIN32_INLINE int
+__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
+{
+  if (__GTHREAD_WIN32_ACTIVE_P ())
+    return TryEnterCriticalSection ((LPCRITICAL_SECTION) __mutex) ? 0 : 1;
+  else
+    return 0;
 }
 
-static inline int
-__gthread_mutex_unlock (__gthread_mutex_t *__mutex)
+#if __GTHREAD_HAS_COND
+
+__GTHREAD_WIN32_COND_INLINE void
+__gthread_cond_init_function (__gthread_cond_t *__cond)
 {
-  if (__gthread_active_p ())
-    {
-      if (InterlockedDecrement (&__mutex->counter) >= 0)
-	return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
-    }
+  InitializeConditionVariable ((PCONDITION_VARIABLE) __cond);
+}
+
+__GTHREAD_WIN32_COND_INLINE int
+__gthread_cond_broadcast (__gthread_cond_t *__cond)
+{
+  WakeAllConditionVariable ((PCONDITION_VARIABLE) __cond);
   return 0;
 }
 
+__GTHREAD_WIN32_COND_INLINE int
+__gthread_cond_signal (__gthread_cond_t *__cond)
+{
+  WakeConditionVariable ((PCONDITION_VARIABLE) __cond);
+  return 0;
+}
+
+__GTHREAD_WIN32_COND_INLINE int
+__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex)
+{
+  if (SleepConditionVariableCS ((PCONDITION_VARIABLE) __cond,
+				(PCRITICAL_SECTION) __mutex,
+				INFINITE))
+    return 0;
+  else
+    return (int) GetLastError ();
+}
+
+extern DWORD __gthr_win32_abs_to_rel_time (const __gthread_time_t *);
+
+__GTHREAD_WIN32_COND_INLINE int
+__gthread_cond_timedwait (__gthread_cond_t *__cond,
+			  __gthread_mutex_t *__mutex,
+			  const __gthread_time_t *__abs_time)
+{
+  DWORD __rel_time = __gthr_win32_abs_to_rel_time (__abs_time);
+  if (SleepConditionVariableCS ((PCONDITION_VARIABLE) __cond,
+				(PCRITICAL_SECTION) __mutex,
+				__rel_time))
+    return 0;
+  else
+    return (int) GetLastError ();
+}
+
+#endif /* __GTHREAD_HAS_COND */
+
+#endif /*  __GTHREAD_HIDE_WIN32API */
+
 static inline void
 __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex)
 {
-  __mutex->counter = -1;
-  __mutex->depth = 0;
-  __mutex->owner = 0;
-  __mutex->sema = CreateSemaphoreW (NULL, 0, 65535, NULL);
+  __gthread_mutex_init_function (__mutex);
 }
 
-static inline int
-__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
+static inline void
+__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
 {
-  if (__gthread_active_p ())
-    {
-      DWORD __me = GetCurrentThreadId();
-      if (InterlockedIncrement (&__mutex->counter) == 0)
-	{
-	  __mutex->depth = 1;
-	  __mutex->owner = __me;
-	}
-      else if (__mutex->owner == __me)
-	{
-	  InterlockedDecrement (&__mutex->counter);
-	  ++(__mutex->depth);
-	}
-      else if (WaitForSingleObject (__mutex->sema, INFINITE) == WAIT_OBJECT_0)
-	{
-	  __mutex->depth = 1;
-	  __mutex->owner = __me;
-	}
-      else
-	{
-	  /* WaitForSingleObject returns WAIT_FAILED, and we can only do
-	     some best-effort cleanup here.  */
-	  InterlockedDecrement (&__mutex->counter);
-	  return 1;
-	}
-    }
-  return 0;
+  __gthread_mutex_destroy (__mutex);
 }
 
 static inline int
-__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex)
+__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex)
 {
-  if (__gthread_active_p ())
-    {
-      DWORD __me = GetCurrentThreadId();
-      if (__GTHR_W32_InterlockedCompareExchange (&__mutex->counter, 0, -1) < 0)
-	{
-	  __mutex->depth = 1;
-	  __mutex->owner = __me;
-	}
-      else if (__mutex->owner == __me)
-	++(__mutex->depth);
-      else
-	return 1;
-    }
-  return 0;
+  return __gthread_mutex_lock (__mutex);
 }
 
 static inline int
 __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex)
 {
-  if (__gthread_active_p ())
-    {
-      --(__mutex->depth);
-      if (__mutex->depth == 0)
-	{
-	  __mutex->owner = 0;
+  return __gthread_mutex_unlock (__mutex);
+}
 
-	  if (InterlockedDecrement (&__mutex->counter) >= 0)
-	    return ReleaseSemaphore (__mutex->sema, 1, NULL) ? 0 : 1;
-	}
-    }
+#if __GTHREAD_HAS_COND
+
+static inline int
+__gthread_cond_destroy (__gthread_cond_t *__cond ATTRIBUTE_UNUSED)
+{
   return 0;
 }
 
 static inline int
-__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex)
+__gthread_cond_wait_recursive (__gthread_cond_t *__cond,
+			       __gthread_recursive_mutex_t *__mutex)
 {
-  CloseHandle ((HANDLE) __mutex->sema);
-  return 0;
+  return __gthread_cond_wait (__cond, __mutex);
 }
 
-#endif /*  __GTHREAD_HIDE_WIN32API */
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/libgcc/config/i386/libgcc-mingw.ver b/libgcc/config/i386/libgcc-mingw.ver
new file mode 100644
index 00000000000..89f8741f9de
--- /dev/null
+++ b/libgcc/config/i386/libgcc-mingw.ver
@@ -0,0 +1,23 @@
+# Copyright (C) 2022 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+GCC_13 {
+  __gthr_win32_create
+  __gthr_win32_join
+  __gthr_win32_self
+}
diff --git a/libgcc/config/i386/t-gthr-win32 b/libgcc/config/i386/t-gthr-win32
index e7380d6f6e4..c2726e23794 100644
--- a/libgcc/config/i386/t-gthr-win32
+++ b/libgcc/config/i386/t-gthr-win32
@@ -1,2 +1,6 @@
-# We hide calls to w32api needed for w32 thread support here:
-LIB2ADD = $(srcdir)/config/i386/gthr-win32.c
+# We need a unique module interfacing with the Win32 API for thread support.
+LIB2ADDEH += $(srcdir)/config/i386/gthr-win32-thread.c
+# We hide calls to the Win32 API needed for condition variable support here.
+LIB2ADD_ST += $(srcdir)/config/i386/gthr-win32-cond.c
+# We hide calls to the Win32 API needed for the rest here.
+LIB2ADD_ST += $(srcdir)/config/i386/gthr-win32.c
diff --git a/libgcc/config/i386/t-slibgcc-mingw b/libgcc/config/i386/t-slibgcc-mingw
new file mode 100644
index 00000000000..f4ad0a8ede3
--- /dev/null
+++ b/libgcc/config/i386/t-slibgcc-mingw
@@ -0,0 +1 @@
+SHLIB_MAPFILES += $(srcdir)/config/i386/libgcc-mingw.ver
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 6f672924a73..d3556441777 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -678,10 +678,13 @@ dnl Set up *_FLAGS and *FLAGS variables for all sundry Makefile.am's.
 dnl (SECTION_FLAGS is done under CHECK_COMPILER_FEATURES.)
 dnl
 dnl Substs:
+dnl  CPPFLAGS
 dnl  OPTIMIZE_CXXFLAGS
 dnl  WARN_FLAGS
 dnl
 AC_DEFUN([GLIBCXX_EXPORT_FLAGS], [
+  AC_SUBST(CPPFLAGS)
+
   # Optimization flags that are probably a good idea for thrill-seekers. Just
   # uncomment the lines below and make, everything else is ready to go...
   # Alternatively OPTIMIZE_CXXFLAGS can be set in configure.host.
@@ -1352,6 +1355,10 @@ AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_TIME], [
       cygwin*)
         ac_has_nanosleep=yes
         ;;
+      mingw*)
+        ac_has_win32_sleep=yes
+        ac_has_sched_yield=yes
+        ;;
       darwin*)
         ac_has_nanosleep=yes
         ac_has_sched_yield=yes
@@ -1537,6 +1544,9 @@ AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_TIME], [
   if test x"$ac_has_nanosleep" = x"yes"; then
     AC_DEFINE(_GLIBCXX_USE_NANOSLEEP, 1,
       [ Defined if nanosleep is available. ])
+  elif test x"$ac_has_win32_sleep" = x"yes"; then
+    AC_DEFINE(_GLIBCXX_USE_WIN32_SLEEP, 1,
+      [Defined if Sleep exists.])
   else
       AC_MSG_CHECKING([for sleep])
       AC_TRY_COMPILE([#include <unistd.h>],
@@ -1557,20 +1567,7 @@ AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_TIME], [
       AC_MSG_RESULT($ac_has_usleep)
   fi
 
-  if test x"$ac_has_nanosleep$ac_has_sleep" = x"nono"; then
-      ac_no_sleep=yes
-      AC_MSG_CHECKING([for Sleep])
-      AC_TRY_COMPILE([#include <windows.h>],
-                     [Sleep(1)],
-                     [ac_has_win32_sleep=yes],[ac_has_win32_sleep=no])
-      if test x"$ac_has_win32_sleep" = x"yes"; then
-        AC_DEFINE(HAVE_WIN32_SLEEP,1, [Defined if Sleep exists.])
-	ac_no_sleep=no
-      fi
-      AC_MSG_RESULT($ac_has_win32_sleep)
-  fi
-
-  if test x"$ac_no_sleep" = x"yes"; then
+  if test x"$ac_has_nanosleep$ac_has_win32_sleep$ac_has_sleep" = x"nonono"; then
     AC_DEFINE(_GLIBCXX_NO_SLEEP,1, [Defined if no way to sleep is available.])
   fi
 
@@ -3987,6 +3984,15 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
   case $target_thread_file in
     posix)
       CXXFLAGS="$CXXFLAGS -DSUPPORTS_WEAK -DGTHREAD_USE_WEAK -D_PTHREADS"
+      ;;
+    win32)
+      CXXFLAGS="$CXXFLAGS -D_WIN32_THREADS"
+      # The support of condition variables is disabled by default in
+      # the Win32 gthreads library, so enable it on explicit request.
+      if test x$enable_libstdcxx_threads = xyes; then
+        CXXFLAGS="$CXXFLAGS -D_WIN32_WINNT=0x0600"
+      fi
+      ;;
   esac
 
   AC_MSG_CHECKING([whether it can be safely assumed that mutex_timedlock is available])
@@ -3997,6 +4003,9 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
       #if (defined(_PTHREADS) \
 	  && (!defined(_POSIX_TIMEOUTS) || _POSIX_TIMEOUTS <= 0))
       #error
+      // In case of Win32 threads there is no support.
+      #elif defined(_WIN32_THREADS)
+      #error
       #endif
     ], [ac_gthread_use_mutex_timedlock=1], [ac_gthread_use_mutex_timedlock=0])
 
@@ -4043,6 +4052,11 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [
              [],
              [#include "gthr.h"])
     fi
+
+    # See above for the rationale.
+    if test $target_thread_file = win32; then
+      CPPFLAGS="$CPPFLAGS -D_WIN32_WINNT=0x0600"
+    fi
   fi
 
   AC_CHECK_HEADER(semaphore.h, [
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index acdfa999543..8bec1b2c601 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -525,9 +525,6 @@
 /* Define to 1 if you have the <wctype.h> header file. */
 #undef HAVE_WCTYPE_H
 
-/* Defined if Sleep exists. */
-#undef HAVE_WIN32_SLEEP
-
 /* Define if writev is available in <sys/uio.h>. */
 #undef HAVE_WRITEV
 
@@ -1028,6 +1025,9 @@
 /* Define if code specialized for wchar_t should be used. */
 #undef _GLIBCXX_USE_WCHAR_T
 
+/* Defined if Sleep exists. */
+#undef _GLIBCXX_USE_WIN32_SLEEP
+
 /* Define to 1 if a verbose library is built, or 0 otherwise. */
 #undef _GLIBCXX_VERBOSE
 
diff --git a/libstdc++-v3/config/os/mingw32-w64/os_defines.h b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
index f9ccc08ef8e..ee02ff82e86 100644
--- a/libstdc++-v3/config/os/mingw32-w64/os_defines.h
+++ b/libstdc++-v3/config/os/mingw32-w64/os_defines.h
@@ -85,6 +85,9 @@
 // their dtors are called
 #define _GLIBCXX_THREAD_ATEXIT_WIN32 1
 
+// Enable use of GetSystemInfo to implement get_nprocs
+#define _GLIBCXX_USE_GET_NPROCS_WIN32 1
+
 // See libstdc++/59807
 #define _GTHREAD_USE_MUTEX_INIT_FUNC 1
 
diff --git a/libstdc++-v3/config/os/mingw32/os_defines.h b/libstdc++-v3/config/os/mingw32/os_defines.h
index 590aa31f81f..69f4bc0abea 100644
--- a/libstdc++-v3/config/os/mingw32/os_defines.h
+++ b/libstdc++-v3/config/os/mingw32/os_defines.h
@@ -75,6 +75,9 @@
 #define _GLIBCXX_LLP64 1
 #endif
 
+// Enable use of GetSystemInfo to implement get_nprocs
+#define _GLIBCXX_USE_GET_NPROCS_WIN32 1
+
 // See libstdc++/59807
 #define _GTHREAD_USE_MUTEX_INIT_FUNC 1
 
diff --git a/libstdc++-v3/src/c++11/thread.cc b/libstdc++-v3/src/c++11/thread.cc
index a54bc3e939a..a8038979090 100644
--- a/libstdc++-v3/src/c++11/thread.cc
+++ b/libstdc++-v3/src/c++11/thread.cc
@@ -34,7 +34,7 @@
 #ifndef _GLIBCXX_USE_NANOSLEEP
 # ifdef _GLIBCXX_HAVE_SLEEP
 #  include <unistd.h>
-# elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
+# elif defined(_GLIBCXX_USE_WIN32_SLEEP)
 #  include <windows.h>
 # elif defined _GLIBCXX_NO_SLEEP && defined _GLIBCXX_HAS_GTHREADS
 // We expect to be able to sleep for targets that support multiple threads:
@@ -62,6 +62,16 @@ static inline int get_nprocs()
  return 0;
 }
 # define _GLIBCXX_NPROCS get_nprocs()
+#elif defined(_GLIBCXX_USE_GET_NPROCS_WIN32)
+#define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+static inline int get_nprocs()
+{
+  SYSTEM_INFO sysinfo;
+  GetSystemInfo (&sysinfo);
+  return (int)sysinfo.dwNumberOfProcessors;
+}
+# define _GLIBCXX_NPROCS get_nprocs()
 #elif defined(_GLIBCXX_USE_SC_NPROCESSORS_ONLN)
 # include <unistd.h>
 # define _GLIBCXX_NPROCS sysconf(_SC_NPROCESSORS_ONLN)
@@ -254,7 +264,7 @@ namespace this_thread
 	__s = chrono::duration_cast<chrono::seconds>(target - now);
 	__ns = chrono::duration_cast<chrono::nanoseconds>(target - (now + __s));
     }
-#elif defined(_GLIBCXX_HAVE_WIN32_SLEEP)
+#elif defined(_GLIBCXX_USE_WIN32_SLEEP)
     unsigned long ms = __ns.count() / 1000000;
     if (__ns.count() > 0 && ms == 0)
       ms = 1;
diff --git a/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/errc_std_c++0x.cc b/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/errc_std_c++0x.cc
index 6670b22ce7f..ebf7147cdc0 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/errc_std_c++0x.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/headers/system_error/errc_std_c++0x.cc
@@ -70,7 +70,10 @@ void test01()
   TEST_ERRC(network_reset);
   TEST_ERRC(network_unreachable);
   TEST_ERRC(no_buffer_space);
+
+#ifdef ECHILD
   TEST_ERRC(no_child_process);
+#endif
 
 #ifdef ENOLINK
   TEST_ERRC(no_link);
@@ -86,7 +89,10 @@ void test01()
   TEST_ERRC(no_message);
 #endif
   TEST_ERRC(no_protocol_option);
+
+#ifdef ENOSPC
   TEST_ERRC(no_space_on_device);
+#endif
 
 #ifdef ENOSR
   TEST_ERRC(no_stream_resources);
@@ -105,16 +111,26 @@ void test01()
 
   TEST_ERRC(not_connected);
   TEST_ERRC(not_enough_memory);
+
+#ifdef ENOTSUP
   TEST_ERRC(not_supported);
+#endif
 
 #ifdef ECANCELED
   TEST_ERRC(operation_canceled);
 #endif
 
   TEST_ERRC(operation_in_progress);
+
+#ifdef EPERM
   TEST_ERRC(operation_not_permitted);
+#endif
+
   TEST_ERRC(operation_not_supported);
+
+#ifdef EWOULDBLOCK
   TEST_ERRC(operation_would_block);
+#endif
 
 #ifdef EOWNERDEAD
   TEST_ERRC(owner_dead);
@@ -144,7 +160,10 @@ void test01()
   TEST_ERRC(text_file_busy);
 #endif
 
+#ifdef ETIMEDOUT
   TEST_ERRC(timed_out);
+#endif
+
   TEST_ERRC(too_many_files_open_in_system);
   TEST_ERRC(too_many_files_open);
   TEST_ERRC(too_many_links);
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 635f16db4e8..ebbf12ac7d0 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -510,6 +510,15 @@ proc v3_target_compile { source dest type options } {
 	}
     }
 
+    # Small adjustment for MinGW hosts.
+    if { $dest == "/dev/null" && [ishost "*-*-mingw*"] } {
+	if { $type == "executable" } {
+	    set dest "x.exe"
+	} else {
+	    set dest "nul"
+	}
+    }
+
     lappend options "compiler=$cxx_final"
     lappend options "timeout=[timeout_value]"
 
@@ -1147,7 +1156,9 @@ proc check_effective_target_gthreads_timed { } {
 # Return 1 if either nanosleep or sleep is available, 0 otherwise.
 proc check_v3_target_sleep { } {
     return [check_v3_target_prop_cached et_sleep {
-	set cond "defined _GLIBCXX_USE_NANOSLEEP || defined _GLIBCXX_HAVE_SLEEP"
+	set cond "defined _GLIBCXX_USE_NANOSLEEP"
+	set cond "$cond || defined _GLIBCXX_USE_WIN32_SLEEP"
+	set cond "$cond || defined _GLIBCXX_HAVE_SLEEP"
 	return [v3_check_preprocessor_condition sleep $cond]
     }]
 }
@@ -1191,6 +1202,7 @@ proc check_v3_target_binary_io { } {
 proc check_v3_target_nprocs { } {
     return [check_v3_target_prop_cached et_nprocs {
 	set cond "defined _GLIBCXX_USE_GET_NPROCS"
+	set cond "$cond || defined _GLIBCXX_USE_GET_NPROCS_WIN32"
 	set cond "$cond || defined _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP"
 	set cond "$cond || defined _GLIBCXX_USE_SYSCTL_HW_NCPU"
 	set cond "$cond || defined _GLIBCXX_USE_SC_NPROCESSORS_ONLN"

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-31  9:18       ` Eric Botcazou
@ 2022-10-31 15:22         ` i.nixman
  2022-12-18 11:14           ` Jonathan Yong
  2022-11-01  5:22         ` i.nixman
  2022-12-16 17:18         ` Jonathan Wakely
  2 siblings, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-10-31 15:22 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: jwakely, libstdc++, 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  <ebotcazou@adacore.com>
> 
> 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.
> 	(__gthread_key_delete): Minor tweak.
> 	(__gthread_getspecific): Likewise.
> 	(__gthread_setspecific): Likewise.
> 	(__gthread_mutex_init_function): Reimplement.
> 	(__gthread_mutex_destroy): Likewise.
> 	(__gthread_mutex_lock): Likewise.
> 	(__gthread_mutex_trylock): Likewise.
> 	(__gthread_mutex_unlock): Likewise.
> 	(__gthr_win32_abs_to_rel_time): Declare.
> 	(__gthread_recursive_mutex_init_function): Reimplement.
> 	(__gthread_recursive_mutex_destroy): Likewise.
> 	(__gthread_recursive_mutex_lock): Likewise.
> 	(__gthread_recursive_mutex_trylock): Likewise.
> 	(__gthread_recursive_mutex_unlock): Likewise.
> 	(__gthread_cond_destroy): New inline function.
> 	(__gthread_cond_wait_recursive): Likewise.
> 	* config/i386/gthr-win32.c: Delete everything.
> 	Include gthr-win32.h to get the out-of-line version of inline 
> routines.
> 	Add compile-time checks for the local version of the Win32 types.
> 	* config/i386/gthr-win32-cond.c: New file.
> 	* config/i386/gthr-win32-thread.c: Likewise.
> 	* config/i386/t-gthr-win32: Add config/i386/gthr-win32-thread.c to the
> 	EH part, config/i386/gthr-win32-cond.c and config/i386/gthr-win32.c to
> 	the static version of libgcc.
> 	* config/i386/t-slibgcc-mingw: New file.
> 	* config/i386/libgcc-mingw.ver: Likewise.
> libstdc++-v3/
> 	* acinclude.m4 (GLIBCXX_EXPORT_FLAGS): Substitute CPPFLAGS.
> 	(GLIBCXX_ENABLE_LIBSTDCXX_TIME): Set ac_has_sched_yield and
> 	ac_has_win32_sleep to yes for MinGW.  Change HAVE_WIN32_SLEEP
> 	into _GLIBCXX_USE_WIN32_SLEEP.
> 	(GLIBCXX_CHECK_GTHREADS): Add _WIN32_THREADS to compilation flags for
> 	Win32 threads and force _GTHREAD_USE_MUTEX_TIMEDLOCK to 0 for them.
> 	Add -D_WIN32_WINNT=0x0600 to compilation flags if yes was configured
> 	and add it to CPPFLAGS on success.
> 	* config.h.in: Regenerate.
> 	* configure: Likewise.
> 	* config/os/mingw32-w64/os_defines.h (_GLIBCXX_USE_GET_NPROCS_WIN32):
> 	Define to 1.
> 	* config/os/mingw32/os_defines.h (_GLIBCXX_USE_GET_NPROCS_WIN32): 
> Ditto
> 	* src/c++11/thread.cc (get_nprocs): Provide Win32 implementation if
> 	_GLIBCXX_USE_GET_NPROCS_WIN32 is defined.  Replace HAVE_WIN32_SLEEP
> 	with USE_WIN32_SLEEP.
> 	* testsuite/19_diagnostics/headers/system_error/errc_std_c++0x.cc: Add
> 	missing conditional compilation.
> 	* testsuite/lib/libstdc++.exp (check_v3_target_sleep): Add support for
> 	_GLIBCXX_USE_WIN32_SLEEP.
> 	(check_v3_target_nprocs): Likewise for _GLIBCXX_USE_GET_NPROCS_WIN32.

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-31  9:18       ` Eric Botcazou
  2022-10-31 15:22         ` i.nixman
@ 2022-11-01  5:22         ` i.nixman
  2022-11-01  9:09           ` Eric Botcazou
  2022-12-16 17:18         ` Jonathan Wakely
  2 siblings, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-11-01  5:22 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: i.nixman, libstdc++, 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-11-01  5:22         ` i.nixman
@ 2022-11-01  9:09           ` Eric Botcazou
  2022-11-02 12:05             ` i.nixman
  0 siblings, 1 reply; 58+ messages in thread
From: Eric Botcazou @ 2022-11-01  9:09 UTC (permalink / raw)
  To: i.nixman; +Cc: libstdc++, gcc-patches

> 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?

Run autoheader + autoconf in the libstdc++-v3 source repository.

-- 
Eric Botcazou



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-11-01  9:09           ` Eric Botcazou
@ 2022-11-02 12:05             ` i.nixman
  2022-11-02 21:27               ` Eric Botcazou
  0 siblings, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-11-02 12:05 UTC (permalink / raw)
  To: libstdc++, 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-11-02 12:05             ` i.nixman
@ 2022-11-02 21:27               ` Eric Botcazou
  2022-11-02 21:40                 ` i.nixman
  0 siblings, 1 reply; 58+ messages in thread
From: Eric Botcazou @ 2022-11-02 21:27 UTC (permalink / raw)
  To: i.nixman; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 638 bytes --]

> 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)

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.

-- 
Eric Botcazou

[-- Attachment #2: t.cc --]
[-- Type: text/x-c++src, Size: 600 bytes --]

#include <iostream>
#include <vector>
#include <mutex>
#include <condition_variable>
#include <thread>

#define NUM_THREADS 4

std::condition_variable cond;
std::mutex mx;
int started = 0;

void
do_thread ()
{
  std::unique_lock<std::mutex> lock(mx);
  std::cout << "Start thread " << started << std::endl;
  if(++started >= NUM_THREADS)
    cond.notify_all();
  else
    cond.wait(lock);
}

int
main ()
{
  std::vector<std::thread> vec;
  for (int i = 0; i < NUM_THREADS; ++i)
    vec.emplace_back(&do_thread);
  for (int i = 0; i < NUM_THREADS; ++i)
    vec[i].join();
  vec.clear();
  return 0;
}

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-11-02 21:27               ` Eric Botcazou
@ 2022-11-02 21:40                 ` i.nixman
  0 siblings, 0 replies; 58+ messages in thread
From: i.nixman @ 2022-11-02 21:40 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: libstdc++, 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-31  9:18       ` Eric Botcazou
  2022-10-31 15:22         ` i.nixman
  2022-11-01  5:22         ` i.nixman
@ 2022-12-16 17:18         ` Jonathan Wakely
  2022-12-16 19:20           ` Eric Botcazou
  2 siblings, 1 reply; 58+ messages in thread
From: Jonathan Wakely @ 2022-12-16 17:18 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: i.nixman, libstdc++, gcc-patches, Jonathan Yong

[-- Attachment #1: Type: text/plain, Size: 8136 bytes --]

On Mon, 31 Oct 2022 at 09:19, Eric Botcazou via Libstdc++
<libstdc++@gcc.gnu.org> wrote:
> 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.

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.

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.


> 2022-10-31  Eric Botcazou  <ebotcazou@adacore.com>
>
> 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.
>         (__gthread_key_delete): Minor tweak.
>         (__gthread_getspecific): Likewise.
>         (__gthread_setspecific): Likewise.
>         (__gthread_mutex_init_function): Reimplement.
>         (__gthread_mutex_destroy): Likewise.
>         (__gthread_mutex_lock): Likewise.
>         (__gthread_mutex_trylock): Likewise.
>         (__gthread_mutex_unlock): Likewise.
>         (__gthr_win32_abs_to_rel_time): Declare.
>         (__gthread_recursive_mutex_init_function): Reimplement.
>         (__gthread_recursive_mutex_destroy): Likewise.
>         (__gthread_recursive_mutex_lock): Likewise.
>         (__gthread_recursive_mutex_trylock): Likewise.
>         (__gthread_recursive_mutex_unlock): Likewise.
>         (__gthread_cond_destroy): New inline function.
>         (__gthread_cond_wait_recursive): Likewise.
>         * config/i386/gthr-win32.c: Delete everything.
>         Include gthr-win32.h to get the out-of-line version of inline routines.
>         Add compile-time checks for the local version of the Win32 types.
>         * config/i386/gthr-win32-cond.c: New file.
>         * config/i386/gthr-win32-thread.c: Likewise.
>         * config/i386/t-gthr-win32: Add config/i386/gthr-win32-thread.c to the
>         EH part, config/i386/gthr-win32-cond.c and config/i386/gthr-win32.c to
>         the static version of libgcc.
>         * config/i386/t-slibgcc-mingw: New file.
>         * config/i386/libgcc-mingw.ver: Likewise.
> libstdc++-v3/
>         * acinclude.m4 (GLIBCXX_EXPORT_FLAGS): Substitute CPPFLAGS.
>         (GLIBCXX_ENABLE_LIBSTDCXX_TIME): Set ac_has_sched_yield and
>         ac_has_win32_sleep to yes for MinGW.  Change HAVE_WIN32_SLEEP
>         into _GLIBCXX_USE_WIN32_SLEEP.
>         (GLIBCXX_CHECK_GTHREADS): Add _WIN32_THREADS to compilation flags for
>         Win32 threads and force _GTHREAD_USE_MUTEX_TIMEDLOCK to 0 for them.
>         Add -D_WIN32_WINNT=0x0600 to compilation flags if yes was configured
>         and add it to CPPFLAGS on success.
>         * config.h.in: Regenerate.
>         * configure: Likewise.
>         * config/os/mingw32-w64/os_defines.h (_GLIBCXX_USE_GET_NPROCS_WIN32):
>         Define to 1.
>         * config/os/mingw32/os_defines.h (_GLIBCXX_USE_GET_NPROCS_WIN32): Ditto
>         * src/c++11/thread.cc (get_nprocs): Provide Win32 implementation if
>         _GLIBCXX_USE_GET_NPROCS_WIN32 is defined.  Replace HAVE_WIN32_SLEEP
>         with USE_WIN32_SLEEP.
>         * testsuite/19_diagnostics/headers/system_error/errc_std_c++0x.cc: Add
>         missing conditional compilation.
>         * testsuite/lib/libstdc++.exp (check_v3_target_sleep): Add support for
>         _GLIBCXX_USE_WIN32_SLEEP.
>         (check_v3_target_nprocs): Likewise for _GLIBCXX_USE_GET_NPROCS_WIN32.
>
> --
> Eric Botcazou

[-- Attachment #2: p13.diff --]
[-- Type: application/x-patch, Size: 56497 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-16 17:18         ` Jonathan Wakely
@ 2022-12-16 19:20           ` Eric Botcazou
  2022-12-22 12:21             ` Jonathan Yong
  0 siblings, 1 reply; 58+ messages in thread
From: Eric Botcazou @ 2022-12-16 19:20 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: i.nixman, libstdc++, gcc-patches, Jonathan Yong

> 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.

-- 
Eric Botcazou



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-10-31 15:22         ` i.nixman
@ 2022-12-18 11:14           ` Jonathan Yong
  0 siblings, 0 replies; 58+ messages in thread
From: Jonathan Yong @ 2022-12-18 11:14 UTC (permalink / raw)
  To: gcc-patches

On 10/31/22 15:22, i.nixman--- via Gcc-patches wrote:
> 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?
> 

I don't see any obvious problems with it, looks OK to me.



^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-16 19:20           ` Eric Botcazou
@ 2022-12-22 12:21             ` Jonathan Yong
  2022-12-22 12:28               ` i.nixman
  0 siblings, 1 reply; 58+ messages in thread
From: Jonathan Yong @ 2022-12-22 12:21 UTC (permalink / raw)
  To: Eric Botcazou, Jonathan Wakely; +Cc: i.nixman, libstdc++, gcc-patches

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?


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-22 12:21             ` Jonathan Yong
@ 2022-12-22 12:28               ` i.nixman
  2022-12-23 23:59                 ` Jonathan Yong
  0 siblings, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-12-22 12:28 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: libstdc++, 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!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-22 12:28               ` i.nixman
@ 2022-12-23 23:59                 ` Jonathan Yong
  2022-12-24  5:58                   ` NightStrike
  2022-12-24  6:22                   ` i.nixman
  0 siblings, 2 replies; 58+ messages in thread
From: Jonathan Yong @ 2022-12-23 23:59 UTC (permalink / raw)
  To: i.nixman; +Cc: libstdc++, gcc-patches


[-- Attachment #1.1.1: Type: text/plain, Size: 881 bytes --]

On 12/22/22 12:28, i.nixman@autistici.org wrote:
> 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!

Done, pushed to master branch. Thanks Eric.


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 7595 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-23 23:59                 ` Jonathan Yong
@ 2022-12-24  5:58                   ` NightStrike
  2022-12-24  6:27                     ` i.nixman
  2022-12-24 13:50                     ` i.nixman
  2022-12-24  6:22                   ` i.nixman
  1 sibling, 2 replies; 58+ messages in thread
From: NightStrike @ 2022-12-24  5:58 UTC (permalink / raw)
  To: Jonathan Yong, fortran; +Cc: i.nixman, libstdc++, gcc-patches

On Fri, Dec 23, 2022 at 7:00 PM Jonathan Yong via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> On 12/22/22 12:28, i.nixman@autistici.org wrote:
> > 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!
>
> Done, pushed to master branch. Thanks Eric.


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,
      |                        ^~~~~~~

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-23 23:59                 ` Jonathan Yong
  2022-12-24  5:58                   ` NightStrike
@ 2022-12-24  6:22                   ` i.nixman
  1 sibling, 0 replies; 58+ messages in thread
From: i.nixman @ 2022-12-24  6:22 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: libstdc++, gcc-patches

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

> Done, pushed to master branch. Thanks Eric.


thank you Jonathan!

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-24  5:58                   ` NightStrike
@ 2022-12-24  6:27                     ` i.nixman
  2022-12-24 13:50                     ` i.nixman
  1 sibling, 0 replies; 58+ messages in thread
From: i.nixman @ 2022-12-24  6:27 UTC (permalink / raw)
  To: NightStrike; +Cc: Eric Botcazou, fortran, libstdc++, 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...

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-24  5:58                   ` NightStrike
  2022-12-24  6:27                     ` i.nixman
@ 2022-12-24 13:50                     ` i.nixman
  2022-12-24 15:42                       ` i.nixman
  1 sibling, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-12-24 13:50 UTC (permalink / raw)
  To: NightStrike; +Cc: fortran, i.nixman, libstdc++, 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...

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-24 13:50                     ` i.nixman
@ 2022-12-24 15:42                       ` i.nixman
  2022-12-24 15:57                         ` i.nixman
  0 siblings, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-12-24 15:42 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: fortran, libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 958 bytes --]

On 2022-12-24 13:50, i.nixman@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!

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cc_none-in-libgfortran-conflict.patch --]
[-- Type: text/x-diff; name=cc_none-in-libgfortran-conflict.patch, Size: 574 bytes --]

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 <windows.h>
-/* 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;

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-24 15:42                       ` i.nixman
@ 2022-12-24 15:57                         ` i.nixman
  2022-12-24 21:22                           ` i.nixman
  0 siblings, 1 reply; 58+ messages in thread
From: i.nixman @ 2022-12-24 15:57 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: fortran, libstdc++, gcc-patches

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

> fixed and tested.
> 
> Jonathan Yong, could you please apply the attached patch too?
> 
> 
> 
> kings regards!

oh no...

please wait.

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-24 15:57                         ` i.nixman
@ 2022-12-24 21:22                           ` i.nixman
  2022-12-25  1:10                             ` Jonathan Yong
  2023-01-09 21:56                             ` Eric Botcazou
  0 siblings, 2 replies; 58+ messages in thread
From: i.nixman @ 2022-12-24 21:22 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: fortran, libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 371 bytes --]

On 2022-12-24 15:57, i.nixman@autistici.org wrote:
> On 2022-12-24 15:42, i.nixman@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!

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: cc_none-in-libgfortran-conflict.patch --]
[-- Type: text/x-diff; name=cc_none-in-libgfortran-conflict.patch, Size: 811 bytes --]

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 <windows.h>
-/* 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 <windows.h>
+#undef CC_NONE
 
 __GTHREAD_WIN32_INLINE int
 __gthread_detach (__gthread_t __thr)

^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-24 21:22                           ` i.nixman
@ 2022-12-25  1:10                             ` Jonathan Yong
  2023-01-09 21:56                             ` Eric Botcazou
  1 sibling, 0 replies; 58+ messages in thread
From: Jonathan Yong @ 2022-12-25  1:10 UTC (permalink / raw)
  To: i.nixman; +Cc: fortran, libstdc++, gcc-patches

On 12/24/22 21:22, i.nixman@autistici.org wrote:
> On 2022-12-24 15:57, i.nixman@autistici.org wrote:
>> On 2022-12-24 15:42, i.nixman@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!

Done, pushed to master, thanks.


^ permalink raw reply	[flat|nested] 58+ messages in thread

* Re: Adding a new thread model to GCC
  2022-12-24 21:22                           ` i.nixman
  2022-12-25  1:10                             ` Jonathan Yong
@ 2023-01-09 21:56                             ` Eric Botcazou
  1 sibling, 0 replies; 58+ messages in thread
From: Eric Botcazou @ 2023-01-09 21:56 UTC (permalink / raw)
  To: Jonathan Yong; +Cc: gcc-patches, fortran, libstdc++, gcc-patches, i.nixman

> fixed now.
> bootstrapped successfully!

Thanks for fixing it.  Another way out is to hide the Win32 API by defining  
__GTHREAD_HIDE_WIN32API like libstdc++ does in its header files.

-- 
Eric Botcazou



^ permalink raw reply	[flat|nested] 58+ messages in thread

end of thread, other threads:[~2023-01-09 21:56 UTC | newest]

Thread overview: 58+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-01 18:34 Adding a new thread model to GCC LIU Hao
2022-10-01 20:02 ` Bernhard Reutner-Fischer
2022-10-02 12:54   ` LIU Hao
2022-10-03  5:03     ` Bernhard Reutner-Fischer
2022-10-04  8:06       ` LIU Hao
2022-10-04 19:45         ` Bernhard Reutner-Fischer
2022-10-04 12:44       ` LIU Hao
2022-10-04 13:13         ` Xi Ruoyao
2022-10-04 13:45           ` LIU Hao
2022-10-05  1:23             ` Xi Ruoyao
2022-10-10 15:56         ` LIU Hao
2022-10-11 13:22           ` LIU Hao
2022-10-14  9:39             ` Jonathan Yong
2022-10-19 13:55               ` Jonathan Yong
2022-10-19 19:53                 ` Bernhard Reutner-Fischer
2022-10-20  1:25                   ` LIU Hao
2022-10-21  9:58 ` Jonathan Wakely
2022-10-21 10:09   ` i.nixman
2022-10-21 10:48     ` Jonathan Wakely
2022-10-21 10:55       ` i.nixman
2022-10-21 11:36     ` LIU Hao
2022-10-21 11:54       ` i.nixman
2022-10-21 12:19         ` LIU Hao
2022-10-21 12:34           ` i.nixman
2022-10-24  3:40             ` LIU Hao
2022-10-24 20:50               ` Jacek Caban
2022-10-21 12:13       ` Jacek Caban
2022-10-21 12:29         ` LIU Hao
2022-10-21 12:40           ` Jacek Caban
2022-10-21 11:44   ` Eric Botcazou
2022-10-21 11:55     ` i.nixman
2022-10-21 12:30       ` Jacek Caban
2022-10-23  0:36         ` NightStrike
2022-10-24  6:53     ` i.nixman
2022-10-24  8:15       ` Eric Botcazou
2022-10-24  8:20         ` i.nixman
2022-10-31  9:18       ` Eric Botcazou
2022-10-31 15:22         ` i.nixman
2022-12-18 11:14           ` Jonathan Yong
2022-11-01  5:22         ` i.nixman
2022-11-01  9:09           ` Eric Botcazou
2022-11-02 12:05             ` i.nixman
2022-11-02 21:27               ` Eric Botcazou
2022-11-02 21:40                 ` i.nixman
2022-12-16 17:18         ` Jonathan Wakely
2022-12-16 19:20           ` Eric Botcazou
2022-12-22 12:21             ` Jonathan Yong
2022-12-22 12:28               ` i.nixman
2022-12-23 23:59                 ` Jonathan Yong
2022-12-24  5:58                   ` NightStrike
2022-12-24  6:27                     ` i.nixman
2022-12-24 13:50                     ` i.nixman
2022-12-24 15:42                       ` i.nixman
2022-12-24 15:57                         ` i.nixman
2022-12-24 21:22                           ` i.nixman
2022-12-25  1:10                             ` Jonathan Yong
2023-01-09 21:56                             ` Eric Botcazou
2022-12-24  6:22                   ` i.nixman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).