Adding a new thread model to GCC

Message ID 0f1f223a-3756-1da3-bd1d-b87edd34e1f9@126.com
State New, archived
Headers
Series Adding a new thread model to GCC |

Commit Message

LIU Hao Oct. 1, 2022, 6:34 p.m. UTC
  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
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(-)
  

Comments

Bernhard Reutner-Fischer Oct. 1, 2022, 8:02 p.m. UTC | #1
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
  
LIU Hao Oct. 2, 2022, 12:54 p.m. UTC | #2
在 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
  
Bernhard Reutner-Fischer Oct. 3, 2022, 5:03 a.m. UTC | #3
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.
>
>
  
LIU Hao Oct. 4, 2022, 8:06 a.m. UTC | #4
在 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
  
LIU Hao Oct. 4, 2022, 12:44 p.m. UTC | #5
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
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;
  
Xi Ruoyao Oct. 4, 2022, 1:13 p.m. UTC | #6
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.)
  
LIU Hao Oct. 4, 2022, 1:45 p.m. UTC | #7
在 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
  
Bernhard Reutner-Fischer Oct. 4, 2022, 7:45 p.m. UTC | #8
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,
  
Xi Ruoyao Oct. 5, 2022, 1:23 a.m. UTC | #9
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.)
  
LIU Hao Oct. 10, 2022, 3:56 p.m. UTC | #10
在 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
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
  
LIU Hao Oct. 11, 2022, 1:22 p.m. UTC | #11
在 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
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__
  
Jonathan Yong Oct. 14, 2022, 9:39 a.m. UTC | #12
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?
  
Jonathan Yong Oct. 19, 2022, 1:55 p.m. UTC | #13
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.
  
Bernhard Reutner-Fischer Oct. 19, 2022, 7:53 p.m. UTC | #14
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,
  
LIU Hao Oct. 20, 2022, 1:25 a.m. UTC | #15
在 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
  
Jonathan Wakely Oct. 21, 2022, 9:58 a.m. UTC | #16
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
  
Li, Pan2 via Gcc-patches Oct. 21, 2022, 10:09 a.m. UTC | #17
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
  
Jonathan Wakely Oct. 21, 2022, 10:48 a.m. UTC | #18
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.
  
Li, Pan2 via Gcc-patches Oct. 21, 2022, 10:55 a.m. UTC | #19
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!
  
LIU Hao Oct. 21, 2022, 11:36 a.m. UTC | #20
在 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
  
Eric Botcazou Oct. 21, 2022, 11:44 a.m. UTC | #21
> 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.
  
Li, Pan2 via Gcc-patches Oct. 21, 2022, 11:54 a.m. UTC | #22
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
  
Li, Pan2 via Gcc-patches Oct. 21, 2022, 11:55 a.m. UTC | #23
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!
  
Jacek Caban Oct. 21, 2022, 12:13 p.m. UTC | #24
> 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
  
LIU Hao Oct. 21, 2022, 12:19 p.m. UTC | #25
在 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
  
LIU Hao Oct. 21, 2022, 12:29 p.m. UTC | #26
在 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
  
Jacek Caban Oct. 21, 2022, 12:30 p.m. UTC | #27
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/
  
Li, Pan2 via Gcc-patches Oct. 21, 2022, 12:34 p.m. UTC | #28
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!
  
Jacek Caban Oct. 21, 2022, 12:40 p.m. UTC | #29
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
  
NightStrike Oct. 23, 2022, 12:36 a.m. UTC | #30
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.
  
LIU Hao Oct. 24, 2022, 3:40 a.m. UTC | #31
在 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
  
Li, Pan2 via Gcc-patches Oct. 24, 2022, 6:53 a.m. UTC | #32
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!
  
Eric Botcazou Oct. 24, 2022, 8:15 a.m. UTC | #33
> 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.
  
Li, Pan2 via Gcc-patches Oct. 24, 2022, 8:20 a.m. UTC | #34
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!
  
Jacek Caban Oct. 24, 2022, 8:50 p.m. UTC | #35
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
  
Eric Botcazou Oct. 31, 2022, 9:18 a.m. UTC | #36
> 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.
  
Li, Pan2 via Gcc-patches Oct. 31, 2022, 3:22 p.m. UTC | #37
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.
  
Li, Pan2 via Gcc-patches Nov. 1, 2022, 5:22 a.m. UTC | #38
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!
  
Eric Botcazou Nov. 1, 2022, 9:09 a.m. UTC | #39
> 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.
  
Li, Pan2 via Gcc-patches Nov. 2, 2022, 12:05 p.m. UTC | #40
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!
  
Eric Botcazou Nov. 2, 2022, 9:27 p.m. UTC | #41
> 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.
  
Li, Pan2 via Gcc-patches Nov. 2, 2022, 9:40 p.m. UTC | #42
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!
  
Jonathan Wakely Dec. 16, 2022, 5:18 p.m. UTC | #43
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
  
Eric Botcazou Dec. 16, 2022, 7:20 p.m. UTC | #44
> 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.
  
Jonathan Yong Dec. 18, 2022, 11:14 a.m. UTC | #45
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.
  
Jonathan Yong Dec. 22, 2022, 12:21 p.m. UTC | #46
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?
  
Li, Pan2 via Gcc-patches Dec. 22, 2022, 12:28 p.m. UTC | #47
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!
  
Jonathan Yong Dec. 23, 2022, 11:59 p.m. UTC | #48
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.
  
NightStrike Dec. 24, 2022, 5:58 a.m. UTC | #49
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,
      |                        ^~~~~~~
  
Li, Pan2 via Gcc-patches Dec. 24, 2022, 6:22 a.m. UTC | #50
On 2022-12-23 23:59, Jonathan Yong wrote:

> Done, pushed to master branch. Thanks Eric.


thank you Jonathan!
  
Li, Pan2 via Gcc-patches Dec. 24, 2022, 6:27 a.m. UTC | #51
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...
  
Li, Pan2 via Gcc-patches Dec. 24, 2022, 1:50 p.m. UTC | #52
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...
  
Li, Pan2 via Gcc-patches Dec. 24, 2022, 3:42 p.m. UTC | #53
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!
  
Li, Pan2 via Gcc-patches Dec. 24, 2022, 3:57 p.m. UTC | #54
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.
  
Li, Pan2 via Gcc-patches Dec. 24, 2022, 9:22 p.m. UTC | #55
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!
  
Jonathan Yong Dec. 25, 2022, 1:10 a.m. UTC | #56
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.
  
Eric Botcazou Jan. 9, 2023, 9:56 p.m. UTC | #57
> 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.
  

Patch

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;