Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a method to retrieve the native handle for a Thread object #37423

Open
john-h-k opened this issue Jun 4, 2020 · 16 comments
Open

Provide a method to retrieve the native handle for a Thread object #37423

john-h-k opened this issue Jun 4, 2020 · 16 comments
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Threading
Milestone

Comments

@john-h-k
Copy link
Contributor

john-h-k commented Jun 4, 2020

Background and Motivation

For native interop, it can be incredibly useful to have access to the underlying thread handle value. For example

  • Working with native fibres
  • Creating custom fibre libraries
  • Performing operations like setting thread affinity

Proposed API

public class Thread
{
+    public IntPtr GetNativeHandle();
+    public bool TryGetNativeHandle(out IntPtr handle);
}

GetNativeHandle would throw an exception (not sure which one) if the Thread object wasn't a true thread (currently afaik they all are, but in the future they could be fibers etc), whereas TryGetNativeHandle would return false

Usage Examples

var thread = ...;

// lock the thread to the first logical processor
Win32.SetThreadAffinityMask(thread.GetNativeHandle(), 1);

Alternative Designs

You could, in this case, just expose SetThreadAffinity - but it doesn't make sense if a thread isn't always a "real" thread

Risks

It isn't a breaking change. If misused, I am sure the handle could do some messy things, but that applies to a lot of the framework 😄

@john-h-k john-h-k added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label Jun 4, 2020
@Dotnet-GitSync-Bot
Copy link
Collaborator

I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label.

@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Jun 4, 2020
@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 4, 2020

cc @tannergooding

@jkotas
Copy link
Member

jkotas commented Jun 4, 2020

What is this API going to return on non-Windows?

@mangod9 mangod9 removed the untriaged New issue has not been triaged by the area owner label Jun 4, 2020
@mangod9 mangod9 added this to the Future milestone Jun 4, 2020
@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 4, 2020

I would assume the pthread_t* on linux systems, and on other systems the type the runtime uses to create them with the OS

@mangod9
Copy link
Member

mangod9 commented Jun 4, 2020

@kouvel fyi..

@jkotas
Copy link
Member

jkotas commented Jun 4, 2020

The problem is that there are typically number of different kinds of thread handles. For example, OSX has pthread_t*, mach_port_t and TID. Even pthread_t* on Linux is not the ubiquitous thread ID. For example, the Linux OS syscalls take pid_t, not pthread_t*.

Working with native fibres
Creating custom fibre libraries

.NET does not work with Windows fibres for fundamendal reasons. This API won't make it possible.

@tannergooding
Copy link
Member

Isn't pid_t the process ID and not the thread handle?

@janvorli
Copy link
Member

janvorli commented Jun 4, 2020

pid_t is used for both process id and thread id (gettid() returns it for current thread, for example)

@tannergooding
Copy link
Member

Thanks! For reference: https://man7.org/linux/man-pages/man2/gettid.2.html

In a single-threaded process, the thread ID is equal to the process ID (PID, as returned by getpid(2)). In a multithreaded process, all threads have the same PID, but each one has a unique TID.
...
The thread ID returned by this call is not the same thing as a POSIX thread ID (i.e., the opaque value returned by pthread_self(3)).

@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 4, 2020

.NET does not work with Windows fibres for fundamendal reasons. This API won't make it possible.

is it specific to how the win32 fibre implementation works? - or is it fundamentally impossible to use fibres at all in .NET

@jkotas
Copy link
Member

jkotas commented Jun 4, 2020

or is it fundamentally impossible to use fibres at all in .NET

Correct. We do not support running managed code on fibers. If you run managed code on fibers, you will get arbitrary crashes.

@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 4, 2020

If you run managed code on fibers, you will get arbitrary crashes.

Ah, my code already does that so it's fine 😆

@john-h-k
Copy link
Contributor Author

john-h-k commented Jun 4, 2020

Being able to do things like set affinity would still be useful, I think. Althought, there could be a managed API to do that specific thing

@HighPerfDotNet
Copy link

HighPerfDotNet commented Mar 20, 2021

I think I've run into changed behavior related to this when trying to port .NET Framework application that was successful at setting ideal processor affinity but that no longer works in .NET 5, the following code no longer matches current thread id:

/* --------------------------------------------------------------------------------- */

// note: it's obsolte, but the same value can be had via Thread.CurrentThread.ManagedThreadId -
// giving exact code as it worked for 10+ years.

int iCurThreadID=AppDomain.GetCurrentThreadId();

foreach (ProcessThread oPT in Process.GetCurrentProcess().Threads)
{

if (oPT.Id==iCurThreadID)
{
	oPT.PriorityBoostEnabled=true;
	oPT.IdealProcessor=iProcAffinity;
	oPT.ProcessorAffinity=new IntPtr(1L<<iProcAffinity);
	break;
}

}

/* --------------------------------------------------------------------------------- */

How are we supported to set processor affinity for current managed thread?

@deeprobin
Copy link
Contributor

deeprobin commented Jul 11, 2022

API-Shape looks good to me.
Imo, we should consider using the CallerMustBeUnsafe (see proposal) attribute.

@deeprobin
Copy link
Contributor

Alternative: A property called NativeHandle, UnderlyingHandle or just Handle to be conform with dotnet/winforms#8833.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Threading
Projects
None yet
Development

No branches or pull requests

8 participants