Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-30 Thread Eric Botcazou
> 0) complexifies comparison of thread IDs without obvious benefits, and

The reverse argument is also true: using IDs would complexify everything else 
with the only benefit of simplifying the equal primitive.

> 1) does not work reliably because handles can be duplicated, and

That's pure FUD.

> 2) makes `__gthread_self()` return invalid handles in detached threads.

Admittedly, but this can be fixed if this is deemed necessary by clearing the 
thread descriptor when detaching the thread.

-- 
Eric Botcazou


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-29 Thread Liu Hao
在 2019/7/29 22:43, JonY 写道:
> 
> Any updates?
> 

No. I am still under the impression that using thread handles as
`std::thread::id`s:

0) complexifies comparison of thread IDs without obvious benefits, and
1) does not work reliably because handles can be duplicated, and
2) makes `__gthread_self()` return invalid handles in detached threads.


-- 
Best regards,
LH_Mouse



signature.asc
Description: OpenPGP digital signature


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-29 Thread JonY
On 7/3/19 12:55 PM, Liu Hao wrote:
> 在 2019/7/2 下午8:27, Jonathan Wakely 写道:
>>
>> What do you mean by "unclosed thread"? If I read it correctly, the MSDN
>> page
>> refers to closing a handle (which makes sense), not closing a thread.
>>
> 
> Yes, it meant a thread which has terminated but not deleted due to some
> handles left open.
> 
> 
>>> This could also mean that there is no effect way to denote a thread
>>> uniquely. As a consequence libstdc++ may have to its own bookkeeping
>>> mechanism.
>>
>> As I said in my last mail, libstdc++ does not need a way to denote a
>> thread uniquely.
>>
> 
> At my last glance at the `__gthread_` interfaces, libstdc++ requires
> thread IDs to be LessThanComparable, which would require retrieval of
> thread IDs by handle, as in `__gthread_equal()`.
> 
> More than that, if my previous vision was correct (a terminated thread
> has no ID associated) then `GetThreadId()` on a thread that has
> terminated would not return a valid thread ID. Fortunately, this seems
> not the case:
> 
> ```c
> #include 
> #include 
> 
> DWORD __stdcall ThreadProc(void* pParam)
>   {
> printf("thread %lu running\n", GetCurrentThreadId());
> return 0;
>   }
> 
> int main(void)
>   {
> HANDLE hThread = CreateThread(0, 0, ThreadProc, 0, CREATE_SUSPENDED, 0);
> printf("thread %lu created\n", GetThreadId(hThread));
> 
> ResumeThread(hThread);
> WaitForSingleObject(hThread, INFINITE);
> printf("thread %lu terminated\n", GetThreadId(hThread));
> 
> CloseHandle(hThread);
> // `hThread` is now invalid; DO NOT PLAY WITH THIS AT HOME!
> printf("thread %lu closed\n", GetThreadId(hThread));
>   }
> ```
> 
> This program outputs
> 
> ```text
> E:\Desktop>gcc test.c -Wall -Wextra -Wpedantic && a.exe
> test.c: In function 'ThreadProc':
> test.c:4:34: warning: unused parameter 'pParam' [-Wunused-parameter]
> 4 | DWORD __stdcall ThreadProc(void* pParam)
>   |~~^~
> thread 9172 created
> thread 9172 running
> thread 9172 terminated
> thread 0 closed
> 
> E:\Desktop>
> ```
> 
> Despite Microsoft's documentation, the identifier of a thread seems
> uncollected as long as there are still handles to the thread. So it
> might be safe to assume that the identifier of an `std::thread` *cannot*
> be reused before it is `join()`'d or `detach()`'d which closes the
> handle stored in the `std::thread` object.
> 
> 

Any updates?



signature.asc
Description: OpenPGP digital signature


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-03 Thread Liu Hao
在 2019/7/2 下午8:27, Jonathan Wakely 写道:
> 
> What do you mean by "unclosed thread"? If I read it correctly, the MSDN
> page
> refers to closing a handle (which makes sense), not closing a thread.
> 

Yes, it meant a thread which has terminated but not deleted due to some
handles left open.


>> This could also mean that there is no effect way to denote a thread
>> uniquely. As a consequence libstdc++ may have to its own bookkeeping
>> mechanism.
> 
> As I said in my last mail, libstdc++ does not need a way to denote a
> thread uniquely.
> 

At my last glance at the `__gthread_` interfaces, libstdc++ requires
thread IDs to be LessThanComparable, which would require retrieval of
thread IDs by handle, as in `__gthread_equal()`.

More than that, if my previous vision was correct (a terminated thread
has no ID associated) then `GetThreadId()` on a thread that has
terminated would not return a valid thread ID. Fortunately, this seems
not the case:

```c
#include 
#include 

DWORD __stdcall ThreadProc(void* pParam)
  {
printf("thread %lu running\n", GetCurrentThreadId());
return 0;
  }

int main(void)
  {
HANDLE hThread = CreateThread(0, 0, ThreadProc, 0, CREATE_SUSPENDED, 0);
printf("thread %lu created\n", GetThreadId(hThread));

ResumeThread(hThread);
WaitForSingleObject(hThread, INFINITE);
printf("thread %lu terminated\n", GetThreadId(hThread));

CloseHandle(hThread);
// `hThread` is now invalid; DO NOT PLAY WITH THIS AT HOME!
printf("thread %lu closed\n", GetThreadId(hThread));
  }
```

This program outputs

```text
E:\Desktop>gcc test.c -Wall -Wextra -Wpedantic && a.exe
test.c: In function 'ThreadProc':
test.c:4:34: warning: unused parameter 'pParam' [-Wunused-parameter]
4 | DWORD __stdcall ThreadProc(void* pParam)
  |~~^~
thread 9172 created
thread 9172 running
thread 9172 terminated
thread 0 closed

E:\Desktop>
```

Despite Microsoft's documentation, the identifier of a thread seems
uncollected as long as there are still handles to the thread. So it
might be safe to assume that the identifier of an `std::thread` *cannot*
be reused before it is `join()`'d or `detach()`'d which closes the
handle stored in the `std::thread` object.


-- 
Best regards,
LH_Mouse



signature.asc
Description: OpenPGP digital signature


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-02 Thread Jonathan Wakely

On 02/07/19 20:14 +0800, Liu Hao wrote:

在 2019/7/2 下午8:00, Jonathan Wakely 写道:

The C++ standard says:

"The library may reuse the value of a thread::id of a terminated
thread that can no longer be joined."

So that's not a reason to use a handle.


According to MSDN [1] a thread ID is valid 'until the thread has been
terminated' so I presume a terminated but unclosed thread does not have
a thread ID.


What do you mean by "unclosed thread"? If I read it correctly, the MSDN page
refers to closing a handle (which makes sense), not closing a thread.


This could also mean that there is no effect way to denote a thread
uniquely. As a consequence libstdc++ may have to its own bookkeeping
mechanism.


As I said in my last mail, libstdc++ does not need a way to denote a
thread uniquely.

I'm not objecting to Eric's use of a HANDLE for a thread::id, as
his justification makes sense. I'm just saying we don't need a unique
ID that outlives the thread, because that's not a requirement.



[1]
https://docs.microsoft.com/en-us/windows/desktop/ProcThread/thread-handles-and-identifiers

--
Best regards,
LH_Mouse







Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-02 Thread Liu Hao
在 2019/7/2 下午8:00, Jonathan Wakely 写道:
> The C++ standard says:
> 
> "The library may reuse the value of a thread::id of a terminated
> thread that can no longer be joined."
> 
> So that's not a reason to use a handle.

According to MSDN [1] a thread ID is valid 'until the thread has been
terminated' so I presume a terminated but unclosed thread does not have
a thread ID.

This could also mean that there is no effect way to denote a thread
uniquely. As a consequence libstdc++ may have to its own bookkeeping
mechanism.


[1]
https://docs.microsoft.com/en-us/windows/desktop/ProcThread/thread-handles-and-identifiers

-- 
Best regards,
LH_Mouse



signature.asc
Description: OpenPGP digital signature


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-02 Thread Jonathan Wakely

On 02/07/19 12:15 +0200, Jacek Caban wrote:


On 02/07/2019 12:12, Jacek Caban wrote:

On 02/07/2019 11:57, Liu Hao wrote:


在 2019/7/2 下午5:19, Eric Botcazou 写道:
It seems inappropriate to use handles as thread identifiers 
(as handles
imply resource ownership and are not unique identifiers); 
thread IDs (as

`DWORD` or `unsigned long`) would be a better alternative.
This was considered but ultimately rejected, as you can do 
nothing with a
thread Id, i.e. you need a handle for everything.  But the 
__gthread_equal

routine does compare the Ids and not the handles.


The `OpenThread()` function can obtain a handle by thread ID. It returns
a real handle that has to be closed when it is out of use. Using the
pseudo handle returned by `GetCurrentThread()` may be more efficient if
the target thread ID is equal to `GetCurrentThreadId()`.



The problem with thread id is that it's not valid nor guaranteed to 
be identical after the thread is terminated. A handle needs to be 
used for that.



I meant unique, not identical.


The C++ standard says:

"The library may reuse the value of a thread::id of a terminated
thread that can no longer be joined."

So that's not a reason to use a handle.



Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-02 Thread Jacek Caban



On 02/07/2019 12:12, Jacek Caban wrote:

On 02/07/2019 11:57, Liu Hao wrote:


在 2019/7/2 下午5:19, Eric Botcazou 写道:
It seems inappropriate to use handles as thread identifiers (as 
handles
imply resource ownership and are not unique identifiers); thread 
IDs (as

`DWORD` or `unsigned long`) would be a better alternative.
This was considered but ultimately rejected, as you can do nothing 
with a
thread Id, i.e. you need a handle for everything.  But the 
__gthread_equal

routine does compare the Ids and not the handles.


The `OpenThread()` function can obtain a handle by thread ID. It returns
a real handle that has to be closed when it is out of use. Using the
pseudo handle returned by `GetCurrentThread()` may be more efficient if
the target thread ID is equal to `GetCurrentThreadId()`.



The problem with thread id is that it's not valid nor guaranteed to be 
identical after the thread is terminated. A handle needs to be used 
for that.



I meant unique, not identical.


Jacek



Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-02 Thread Jacek Caban

On 02/07/2019 11:57, Liu Hao wrote:


在 2019/7/2 下午5:19, Eric Botcazou 写道:

It seems inappropriate to use handles as thread identifiers (as handles
imply resource ownership and are not unique identifiers); thread IDs (as
`DWORD` or `unsigned long`) would be a better alternative.

This was considered but ultimately rejected, as you can do nothing with a
thread Id, i.e. you need a handle for everything.  But the __gthread_equal
routine does compare the Ids and not the handles.


The `OpenThread()` function can obtain a handle by thread ID. It returns
a real handle that has to be closed when it is out of use. Using the
pseudo handle returned by `GetCurrentThread()` may be more efficient if
the target thread ID is equal to `GetCurrentThreadId()`.



The problem with thread id is that it's not valid nor guaranteed to be 
identical after the thread is terminated. A handle needs to be used for 
that.



Jacek



Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-02 Thread Liu Hao
在 2019/7/2 下午5:19, Eric Botcazou 写道:
>> It seems inappropriate to use handles as thread identifiers (as handles
>> imply resource ownership and are not unique identifiers); thread IDs (as
>> `DWORD` or `unsigned long`) would be a better alternative.
> 
> This was considered but ultimately rejected, as you can do nothing with a 
> thread Id, i.e. you need a handle for everything.  But the __gthread_equal 
> routine does compare the Ids and not the handles.
> 

The `OpenThread()` function can obtain a handle by thread ID. It returns
a real handle that has to be closed when it is out of use. Using the
pseudo handle returned by `GetCurrentThread()` may be more efficient if
the target thread ID is equal to `GetCurrentThreadId()`.


-- 
Best regards,
LH_Mouse



signature.asc
Description: OpenPGP digital signature


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-07-02 Thread Eric Botcazou
> It seems inappropriate to use handles as thread identifiers (as handles
> imply resource ownership and are not unique identifiers); thread IDs (as
> `DWORD` or `unsigned long`) would be a better alternative.

This was considered but ultimately rejected, as you can do nothing with a 
thread Id, i.e. you need a handle for everything.  But the __gthread_equal 
routine does compare the Ids and not the handles.

-- 
Eric Botcazou


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-06-28 Thread Liu Hao
在 2019/6/29 上午12:10, Jacek Caban 写道:
> 
> You don't really need to store the whole __gthr_win32_thr_desc in TLS.
> If you stored just the handle, this wouldn't need a destructor.
> 
> 

The handle to be stored in the TLS ('the Handle' for short hereinafter)
should be a real handle, so there are a few scenarios that we should
consider:

0) the Handle should be closed upon the spawned thread's exit; in this
   case a destructor is still necessary to prevent handle leaks.
1) the Handle is closed by the creator via either `*_join()` or
   `*_detach()`; in the latter case the Handle becomes invalid while
   the thread is running, so `*_self()` would return an invalid handle.

It seems inappropriate to use handles as thread identifiers (as handles
imply resource ownership and are not unique identifiers); thread IDs (as
`DWORD` or `unsigned long`) would be a better alternative.


-- 
Best regards,
LH_Mouse



signature.asc
Description: OpenPGP digital signature


Re: [Mingw-w64-public] Fwd: [patch] Reimplement GNU threads library on native Windows

2019-06-28 Thread Jacek Caban

Hi Eric,

On 6/28/19 3:42 PM, NightStrike wrote:

FYI, Eric posted this today to the GCC patches list.  This may be of
great interest to many who would prefer native threads instead of the
winpthreads posix style interface.

Great work, Eric!  I look forward to trying this out!

-- Forwarded message -
From: Eric Botcazou 
Date: Fri, Jun 28, 2019 at 6:51 AM
Subject: [patch] Reimplement GNU threads library on native Windows
To: 
Cc: 


Hi,

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 is the default minimal setting of MinGW-W64.
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 _GTHREADS_USE_COND is defined to 1.

This also changes libstdc++ to setting _GTHREADS_USE_COND to 1 when the switch
--enable-libstdcxx-threads is passed, which means that C++11 threads are still
disabled by default on native Windows and that you need to explicitly pass the
switch to enable them.  The 30_threads chapter of the testsuite is clean.

Tested on i686-pc-mingw32 and x86_64-pc-mingw32, OK for the mainline?



It's indeed great to see this. Thank you!



+/* The implementation strategy for the c++0x thread support is as follows.
+
+   A GNU thread is represented by a Win32 HANDLE that is obtained when the
+   Win32 thread is created, except of course for the initial thread.  This
+   Win32 HANDLE is stored in a descriptor keyed from TLS memory for every
+   thread, so the self routine can return it instead of having to duplicate
+   the pseudo-handle returned by GetCurrentThread each time it is invoked.
+   For the initial thread, this Win32 HANDLE is created during the first
+   call to the self routine using the aforementioned technique.
+
+   Note that the equal routine compares the identifier of threads instead
+   of their Win32 HANDLE, which will give the correct positive answer even
+   in the case where distinct Win32 HANDLEs have been created for the same
+   thread by multiple instances of libgcc included in the link.  */


Note that this will cause handle leaks if used across multiple libgcc 
instances, through.


+#include "gthr-win32.h"
+
+/* The thread descriptor keyed from TLS memory.  */
+struct __gthr_win32_thr_desc
+{
+  void *(*func) (void*);
+  void *args;
+  HANDLE h;
+};
+
+/* The TLS key used by one instance of the library.  */
+static __gthread_key_t __gthr_win32_tls = TLS_OUT_OF_INDEXES;
+
+/* The initialization device for the TLS key.  */
+static __gthread_once_t __gthr_win32_tls_once = __GTHREAD_ONCE_INIT;
+
+/* Initialize the TLS key.  */
+
+static void
+__gthr_win32_tls_init (void)
+{
+  if (__gthread_key_create (&__gthr_win32_tls, free))
+abort ();
+}



You don't really need to store the whole __gthr_win32_thr_desc in TLS. If you 
stored just the handle, this wouldn't need a destructor.


Thanks,
Jacek